mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-18 16:27:34 +01:00
Merge Upsilon-dev
This commit is contained in:
5
Makefile
5
Makefile
@@ -219,3 +219,8 @@ run: compile
|
||||
translations:
|
||||
@echo "TRANSLATIONS"
|
||||
$(Q) ${PYTHON} build/utilities/translate.py
|
||||
|
||||
.PHONY: translations_clean
|
||||
translations_clean:
|
||||
@echo "TRANSLATIONS CLEAN"
|
||||
$(Q) ${PYTHON} build/utilities/translations_clean.py
|
||||
|
||||
@@ -266,7 +266,8 @@ bool AppsContainer::processEvent(Ion::Events::Event event) {
|
||||
}
|
||||
if (event == Ion::Events::BrightnessPlus || event == Ion::Events::BrightnessMinus) {
|
||||
int delta = Ion::Backlight::MaxBrightness/GlobalPreferences::NumberOfBrightnessStates;
|
||||
int direction = (event == Ion::Events::BrightnessPlus) ? Ion::Backlight::NumberOfStepsPerShortcut*delta : -delta*Ion::Backlight::NumberOfStepsPerShortcut;
|
||||
int NumberOfStepsPerShortcut = GlobalPreferences::sharedGlobalPreferences()->brightnessShortcut();
|
||||
int direction = (event == Ion::Events::BrightnessPlus) ? NumberOfStepsPerShortcut*delta : -delta*NumberOfStepsPerShortcut;
|
||||
GlobalPreferences::sharedGlobalPreferences()->setBrightnessLevel(GlobalPreferences::sharedGlobalPreferences()->brightnessLevel()+direction);
|
||||
}
|
||||
return false;
|
||||
@@ -353,6 +354,8 @@ bool AppsContainer::updateBatteryState() {
|
||||
}
|
||||
|
||||
void AppsContainer::refreshPreferences() {
|
||||
m_suspendTimer.reset(GlobalPreferences::sharedGlobalPreferences()->idleBeforeSuspendSeconds()*1000/Timer::TickDuration);
|
||||
m_backlightDimmingTimer.reset(GlobalPreferences::sharedGlobalPreferences()->idleBeforeDimmingSeconds()*1000/Timer::TickDuration);
|
||||
m_window.refreshPreferences();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,39 +1,26 @@
|
||||
#include "backlight_dimming_timer.h"
|
||||
#include "global_preferences.h"
|
||||
#include <ion/backlight.h>
|
||||
#include <ion/events.h>
|
||||
#include <apps/apps_container.h>
|
||||
|
||||
BacklightDimmingTimer::BacklightDimmingTimer() :
|
||||
Timer(k_idleBeforeDimmingDuration/Timer::TickDuration)
|
||||
Timer(GlobalPreferences::sharedGlobalPreferences()->idleBeforeDimmingSeconds()*1000/Timer::TickDuration)
|
||||
{
|
||||
}
|
||||
|
||||
bool BacklightDimmingTimer::fire() {
|
||||
if (m_dimerExecutions == 0) {
|
||||
m_brightnessLevel = GlobalPreferences::sharedGlobalPreferences()->brightnessLevel();
|
||||
m_dimerSteps = m_brightnessLevel / decreaseBy;
|
||||
m_timeToSleep = decreasetime / m_dimerSteps;
|
||||
m_period = m_timeToSleep / Timer::TickDuration;
|
||||
if (m_period == 0) {
|
||||
m_period = 1;
|
||||
bool BacklightDimmingTimer::fire(){
|
||||
int i = Ion::Backlight::brightness();
|
||||
while (i > 0){
|
||||
int t = 20;
|
||||
Ion::Events::Event e = Ion::Events::getEvent(&t);
|
||||
AppsContainer::sharedAppsContainer()->dispatchEvent(e);
|
||||
if (e.isKeyboardEvent()){
|
||||
return false;
|
||||
}
|
||||
resetTimer();
|
||||
|
||||
Ion::Backlight::setBrightness(i);
|
||||
i -= 15;
|
||||
}
|
||||
if (m_dimerExecutions < m_dimerSteps) {
|
||||
m_nextbrightness = (m_brightnessLevel-k_dimBacklightBrightness)/m_dimerSteps * (m_dimerSteps-m_dimerExecutions);
|
||||
Ion::Backlight::setBrightness(m_nextbrightness);
|
||||
resetTimer();
|
||||
} else if (m_dimerExecutions == m_dimerSteps) {
|
||||
Ion::Backlight::setBrightness(k_dimBacklightBrightness);
|
||||
}
|
||||
m_dimerExecutions++;
|
||||
return false;
|
||||
}
|
||||
|
||||
void BacklightDimmingTimer::reset() {
|
||||
m_dimerExecutions = 0;
|
||||
m_period = k_idleBeforeDimmingDuration / Timer::TickDuration;
|
||||
resetTimer();
|
||||
}
|
||||
|
||||
void BacklightDimmingTimer::resetTimer() {
|
||||
BacklightDimmingTimer::m_numberOfTicksBeforeFire = BacklightDimmingTimer::m_period;
|
||||
}
|
||||
|
||||
@@ -6,19 +6,8 @@
|
||||
class BacklightDimmingTimer : public Timer {
|
||||
public:
|
||||
BacklightDimmingTimer();
|
||||
void reset();
|
||||
private:
|
||||
constexpr static int k_idleBeforeDimmingDuration = 30*1000; // In miliseconds
|
||||
constexpr static int k_dimBacklightBrightness = 0;
|
||||
constexpr static int decreaseBy = 15;
|
||||
constexpr static int decreasetime = 1*1000; // In miliseconds
|
||||
int m_dimerExecutions = 0;
|
||||
int m_brightnessLevel;
|
||||
int m_dimerSteps;
|
||||
int m_nextbrightness;
|
||||
float m_timeToSleep; // In miliseconds
|
||||
bool fire() override;
|
||||
void resetTimer();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
CodeAppCapital = "PYTHON"
|
||||
ConsolePrompt = ">>> "
|
||||
ScriptParameters = "..."
|
||||
|
||||
@@ -186,14 +186,11 @@ PythonTurtlePosition = "Aktuelle (x,y) Position zurückgeben"
|
||||
PythonTurtleReset = "Die Zeichnung zurücksetzen"
|
||||
PythonTurtleRight = "Um ein Grad nach rechts drehen"
|
||||
PythonTurtleSetheading = "Ausrichtung auf einen Grad setzen"
|
||||
PythonTurtleSetposition = "Den Igel auf Position setzen"
|
||||
PythonTurtleShowturtle = "Den Igel anzeigen"
|
||||
PythonTurtleSpeed = "Zeichengeschwindigkeit von 0 bis 10"
|
||||
PythonTurtleWrite = "Einen Text anzeigen"
|
||||
PythonUniform = "Fließkommazahl in [a,b]"
|
||||
PythonImportTime = "Time-Modul importieren"
|
||||
PythonTimePrefix = "Zeitmodul-Funktionspräfix"
|
||||
PythonTimeSleep = "Warte für n Sekunden"
|
||||
PythonMonotonic = "Monotone Zeit zurückgeben"
|
||||
PythonFileOpen = "Öffnet eine Datei"
|
||||
PythonFileSeekable = "Kann Datei durchsucht werden?"
|
||||
|
||||
@@ -172,7 +172,6 @@ PythonTurtlePosition = "Return the current (x,y) location"
|
||||
PythonTurtleReset = "Reset the drawing"
|
||||
PythonTurtleRight = "Turn right by a degrees"
|
||||
PythonTurtleSetheading = "Set the orientation to a degrees"
|
||||
PythonTurtleSetposition = "Positioning the turtle"
|
||||
PythonTurtleShowturtle = "Show the turtle"
|
||||
PythonTurtleSpeed = "Drawing speed between 0 and 10"
|
||||
PythonTurtleWrite = "Display a text"
|
||||
@@ -192,8 +191,6 @@ PythonSysImplementation = "Information about Python"
|
||||
PythonSysModules = "Dictionary of loaded modules"
|
||||
PythonSysVersion = "Python language version (string)"
|
||||
PythonSysVersioninfo = "Python language version (tuple)"
|
||||
PythonTimePrefix = "time module function prefix"
|
||||
PythonTimeSleep = "Wait for n second"
|
||||
PythonMonotonic = "Return monotonic time"
|
||||
PythonFileOpen = "Opens a file"
|
||||
PythonFileSeekable = "Tells if seek can be used on a file"
|
||||
|
||||
@@ -172,7 +172,6 @@ PythonTurtlePosition = "Return the current (x,y) location"
|
||||
PythonTurtleReset = "Reset the drawing"
|
||||
PythonTurtleRight = "Turn right by a degrees"
|
||||
PythonTurtleSetheading = "Set the orientation to a degrees"
|
||||
PythonTurtleSetposition = "Colocar la tortuga"
|
||||
PythonTurtleShowturtle = "Show the turtle"
|
||||
PythonTurtleSpeed = "Drawing speed between 0 and 10"
|
||||
PythonTurtleWrite = "Display a text"
|
||||
@@ -192,8 +191,6 @@ PythonSysImplementation = "Information about Python"
|
||||
PythonSysModules = "Dictionary of loaded modules"
|
||||
PythonSysVersion = "Python language version (string)"
|
||||
PythonSysVersioninfo = "Python language version (tuple)"
|
||||
PythonTimePrefix = "time module function prefix"
|
||||
PythonTimeSleep = "Esperar n segundos"
|
||||
PythonMonotonic = "Tiempo monótono de retorno"
|
||||
PythonFileOpen = "Opens a file"
|
||||
PythonFileSeekable = "Tells if seek can be used on a file"
|
||||
|
||||
@@ -172,7 +172,6 @@ PythonTurtlePosition = "Renvoie la position (x,y)"
|
||||
PythonTurtleReset = "Réinitialise le dessin"
|
||||
PythonTurtleRight = "Pivote de a degrés vers la droite"
|
||||
PythonTurtleSetheading = "Met un cap de a degrés"
|
||||
PythonTurtleSetposition = "Positionne la tortue"
|
||||
PythonTurtleShowturtle = "Affiche la tortue"
|
||||
PythonTurtleSpeed = "Vitesse du tracé entre 0 et 10"
|
||||
PythonTurtleWrite = "Affiche un texte"
|
||||
@@ -192,8 +191,6 @@ PythonSysImplementation = "Information sur Python"
|
||||
PythonSysModules = "Dictionnaire des modules chargés"
|
||||
PythonSysVersion = "Version du langage Python (string)"
|
||||
PythonSysVersioninfo = "Version du langage Python (tuple)"
|
||||
PythonTimePrefix = "Préfixe fonction du module temps"
|
||||
PythonTimeSleep = "Attendre n secondes"
|
||||
PythonMonotonic = "Retourne le temps monotone"
|
||||
PythonFileOpen = "Ouvre un fichier"
|
||||
PythonFileSeekable = "Indique si seek peut être utilisé"
|
||||
|
||||
@@ -1,213 +1,210 @@
|
||||
PythonPound = "Megjegyzés"
|
||||
PythonPercent = "Modulo"
|
||||
Python1J = "Képzeletbeli i"
|
||||
PythonLF = "Enter"
|
||||
PythonTab = "Táblázat"
|
||||
PythonAmpersand = "Logikus és"
|
||||
PythonSymbolExp = "logikus exkluzív vagy pedig"
|
||||
PythonVerticalBar = "logikus vagy pedig"
|
||||
PythonImag = "z képzeletbeli része"
|
||||
PythonReal = "z valódi része"
|
||||
PythonSingleQuote = "apostróf"
|
||||
PythonAbs = "Abszolút érték/nagyság"
|
||||
PythonAcos = "Ív (arc) koszinusz"
|
||||
PythonAcosh = "Hiperbolikus arc koszinusz"
|
||||
PythonAppend = "Lista végére hozzáadni x-et"
|
||||
PythonArrow = "(x,y) nyíla (x+dx,y+dy) nyílához"
|
||||
PythonAsin = "Ív (arc) szinusz"
|
||||
PythonAsinh = "Hiperbolikus ív (arc) szinusz"
|
||||
PythonAtan = "Ív (arc) érintö (tan)"
|
||||
PythonAtan2 = "atan(y/x) sámolása"
|
||||
PythonAtanh = "Hiperbolikus ív (arc) érintö (atan)"
|
||||
PythonAxis = "Tengelyeket (xmin,xmax,ymin,ymax)-ra állitani"
|
||||
PythonBar = "Az x lista oszlopdiagramja"
|
||||
PythonBin = "Egész szám konvertálása binárisra"
|
||||
PythonCeil = "Mennyezet"
|
||||
PythonChoice = "Véletlenszerü szám a listában"
|
||||
PythonClear = "A lista ürítése"
|
||||
PythonCmathFunction = "cmath modul funkció elötag"
|
||||
PythonColor = "Rgb (pzk) szín allítása"
|
||||
PythonColorBlack = "Fekete szín"
|
||||
PythonColorBlue = "Kék szín"
|
||||
PythonColorBrown = "Barna szín"
|
||||
PythonColorGreen = "Zöld szín"
|
||||
PythonColorGray = "Szürke szín"
|
||||
PythonColorOrange = "Narancssárga szín"
|
||||
PythonColorPink = "Rózsaszín szín"
|
||||
PythonColorPurple = "Lila szín"
|
||||
PythonColorRed = "Piros szín"
|
||||
PythonColorWhite = "Fehér szín"
|
||||
PythonColorYellow = "Sárga szín"
|
||||
PythonComplex = "A + ib visszaadása"
|
||||
PythonCopySign = "X visszaadása y jelével"
|
||||
PythonCos = "Koszinusz"
|
||||
PythonCosh = "Hiperbolikus koszinusz"
|
||||
PythonCount = "Számolja az x elöfordulását"
|
||||
PythonDegrees = "x konvertálása radiánokrol fokokra"
|
||||
PythonDivMod = "Hányados és maradék"
|
||||
PythonDrawCircle = "Rajzolj egy kört"
|
||||
PythonDrawLine = "Húzzon egy vonalat "
|
||||
PythonDrawString = "Szöveg megjelenítése (x, y)-en"
|
||||
PythonErf = "Hiba funkció"
|
||||
PythonErfc = "Kiegészítö hiba funkció"
|
||||
PythonEval = "Visszaadja az értékelt kifejezést"
|
||||
PythonExp = "Exponenciális függvény"
|
||||
PythonExpm1 = "exp(x)-1 sámitása"
|
||||
PythonFactorial = "x faktorál"
|
||||
PythonFabs = "Abszolút érték"
|
||||
PythonFillRect = "Téglalap töltése"
|
||||
PythonFillCircle = "Kitölti a kört"
|
||||
PythonFillPolygon = "Kitölti a poligont"
|
||||
PythonFloat = "Konvertálása tizedes számra"
|
||||
PythonFloor = "Egész része"
|
||||
PythonFmod = "a modulo b"
|
||||
PythonFrExp = "X mantissája és kiállítója"
|
||||
PythonGamma = "Gamma funkció"
|
||||
PythonGetKeys = "Billentyűk lenyomva"
|
||||
PythonGetPalette = "Téma paletta beszerzése"
|
||||
PythonGetPixel = "Visszatéríti (x,y) színét"
|
||||
PythonGetrandbits = "Váletlenszám visszatérítése k biten"
|
||||
PythonGrid = "Rács megjelenítése/elrejtése"
|
||||
PythonHex = "Decimális szám konvertálása hexadecimális számra"
|
||||
PythonHist = "x hisztográmiája"
|
||||
PythonImportCmath = "cmath modul importálása"
|
||||
PythonImportIon = "Ion modul importálása"
|
||||
PythonImportKandinsky = "Kandinsky modul importálása"
|
||||
PythonImportRandom = "Véletlenszerü modul importálása"
|
||||
PythonImportMath = "math modul importálása"
|
||||
PythonImportMatplotlibPyplot = "matplotlib.pyplot modul importálása"
|
||||
PythonImportNumpy = "ulab.numpy modul importálása"
|
||||
PythonImportScipy = "ulab.scipy modul importálása"
|
||||
PythonImportTurtle = "turtle modul importálása"
|
||||
PythonImportTime = "time modul importálása"
|
||||
PythonIndex = "Az elsö x esemény indexe"
|
||||
PythonInput = "Irjon egy értéket (számot)"
|
||||
PythonInsert = "x-et i. pozícióra helyezze a listában"
|
||||
PythonInt = "egész számra konvertálás"
|
||||
PythonIonFunction = "ion modul funkció elötag"
|
||||
PythonIsFinite = "x véges-e"
|
||||
PythonIsInfinite = "x végtelen-e"
|
||||
PythonIsKeyDown = "True-t válaszol ha a k gomb le van nyomva"
|
||||
PythonBattery = "Az akkumulátor feszültségének visszaadása"
|
||||
PythonBatteryLevel = "Az akkumulátor töltöttségi szintjének visszaadása"
|
||||
PythonBatteryIscharging = "Visszaadja, ha az akkumulátor töltődik"
|
||||
PythonSetBrightness = "Fényerőszint beállítása"
|
||||
PythonGetBrightness = "Get brightness level"
|
||||
PythonIsNaN = "Ellenörizze hogy x nem NaN"
|
||||
PythonKandinskyFunction = "kandinsky modul funkció elötag"
|
||||
PythonLdexp = "frexp ellentéte : x*(2**i)"
|
||||
PythonLength = "Egy targy hossza"
|
||||
PythonLgamma = "Gamma funkció logaritmusa"
|
||||
PythonLog = "a alapú logaritmus"
|
||||
PythonLog10 = "Decimális logaritmus"
|
||||
PythonLog2 = "Bináris logaritmus"
|
||||
PythonMathFunction = "math modul funkció elötag"
|
||||
PythonMatplotlibPyplotFunction = "matplotlib.pyplot elötag"
|
||||
PythonMax = "Maximum"
|
||||
PythonMin = "Minimum"
|
||||
PythonModf = "x-nek tört és egész részei"
|
||||
PythonMonotonic = "Az óra értékét adja vissza"
|
||||
PythonNumpyFunction = "numpy elötag"
|
||||
PythonNumpyFftFunction = "numpy.fft elötag"
|
||||
PythonNumpyLinalgFunction = "numpy.linalg elötag"
|
||||
PythonScipyFunction = "scipy elötag"
|
||||
PythonScipyLinalgFunction = "scipy.linalg elötag"
|
||||
PythonScipyOptimizeFunction = "scipy.optimize elötag"
|
||||
PythonScipySignalFunction = "scipy.signal elötag"
|
||||
PythonScipySpecialFunction = "scipy.special elötag"
|
||||
PythonOct = "Decimális szám konvertálása octális számra"
|
||||
PythonPhase = "z fázisa"
|
||||
PythonPlot = "y-t jelöli x függvényében"
|
||||
PythonPolar = "Verctorizálni"
|
||||
PythonPop = "Az utolsó elemet el törölni"
|
||||
PythonPower = "x y. kitevö"
|
||||
PythonPrint = "Ki irni a elemeket"
|
||||
PythonRadians = "Fokról radiánra konvertálni"
|
||||
PythonRandint = "Véletlen egész szám [a;b] -ban"
|
||||
PythonRandom = "Decimális szám [0;1] -ban"
|
||||
PythonRandomFunction = "random modul funkció elötag"
|
||||
PythonRandrange = "Véletlen szám range(start,stop)-ban"
|
||||
PythonRangeStartStop = "start-tol stop-ig listája"
|
||||
PythonRangeStop = "0 tol stop-ig lista"
|
||||
PythonRect = "Algebrai számra konvertálni"
|
||||
PythonRemove = "Elsö x elöfordulását törolni"
|
||||
PythonReverse = "A lista elemeit megfordítani (másik irány)"
|
||||
PythonRound = "N számjegyre kerekítni"
|
||||
PythonScatter = "(x,y) halmaza"
|
||||
PythonSeed = "Inicializálni a véletlenszám-választót"
|
||||
PythonSetPixel = "Az (x,y) pixel-t ki szinezni"
|
||||
PythonShow = "Mutassa az ábrát"
|
||||
PythonSin = "Szinusz"
|
||||
PythonSinh = "Hiperbolikus szinusz"
|
||||
PythonSleep = "t másodpercre meg állitani a programmot"
|
||||
PythonLocalTime = "Idő konvertálása csomóvá"
|
||||
PythonMktime = "A tuple konvertálása az időben"
|
||||
PythonTime = "Az aktuális időbélyeg letöltése"
|
||||
PythonSetLocaltime = "Idő beállítása egy csomóból"
|
||||
PythonRTCmode = "Aktuális RTC mód"
|
||||
PythonSetRTCmode = "RTC mód beállítása"
|
||||
PythonSort = "A listát rendezni"
|
||||
PythonSqrt = "Négyzetgyök"
|
||||
PythonSum = "Összeadni a lista elemeit"
|
||||
PythonTan = "Érintö (tan)"
|
||||
PythonTanh = "Hiperbolikus érintö (tan)"
|
||||
PythonText = "(x,y) nél egy szöveget irni"
|
||||
PythonTimeFunction = "time funkció elötag"
|
||||
PythonTrunc = "Egész csonka (?)"
|
||||
PythonTurtleBackward = "x pixelt hátra"
|
||||
PythonTurtleCircle = "r pixel sugarú kört rajzolni"
|
||||
PythonTurtleColor = "Toll szinét beállitani"
|
||||
PythonTurtleColorMode = "Szin módot 1.0-ra vagy 255-ra állitani"
|
||||
PythonTurtleForward = "x pixelt elölre"
|
||||
PythonTurtleFunction = "turtle modul funkció elötag"
|
||||
PythonTurtleGoto = "Menjen a (x,y) koordinátákra"
|
||||
PythonTurtleHeading = "Visszaadja az aktuális irányt"
|
||||
PythonTurtleHideturtle = "A teknös elrejtése"
|
||||
PythonTurtleIsdown = "True-t válaszol ha a toll irás pozícióban van"
|
||||
PythonTurtleLeft = "a fokkot forduljon balra"
|
||||
PythonTurtlePendown = "Húzza le a tollat"
|
||||
PythonTurtlePensize = "Állítsa a vonalvastagságot x pixelre"
|
||||
PythonTurtlePenup = "Húzza fel a tollat"
|
||||
PythonTurtlePosition = "Az aktuális (x,y) pozíciót visszaadása"
|
||||
PythonTurtleReset = "Visszaállitani a rajzot (torléssel)"
|
||||
PythonTurtleRight = "a fokkot forduljon jobbra"
|
||||
PythonTurtleSetheading = "a fokokra állítja be az irányt"
|
||||
PythonTurtleSetposition = "A teknös pozicioját allitja"
|
||||
PythonTurtleShowturtle = "A teknöst meg mutatni"
|
||||
PythonTurtleSpeed = "Rajzolási sebesség 0 és 10 között"
|
||||
PythonTurtleWrite = "Szöveg irás"
|
||||
PythonUniform = "Lebegöpontos szám [a,b] -ban"
|
||||
PythonImportTime = "time modul importálása"
|
||||
PythonTimePrefix = "time funkció elötag"
|
||||
PythonTimeSleep = "n másodpercet várni"
|
||||
PythonMonotonic = "Meg fordítani a monoton idö"
|
||||
PythonFileOpen = "Fájl megnyitása"
|
||||
PythonFileSeekable = "Seek-et lehete használni"
|
||||
PythonFileSeek = "A kurzort áthelyezni"
|
||||
PythonFileTell = "Visszaadja a kurzor helye"
|
||||
PythonFileClose = "Bezárni egy fájlt"
|
||||
PythonFileClosed = "True ha a fájl bezárva"
|
||||
PythonFileRead = "Olvas 16 bájtig"
|
||||
PythonFileWrite = "b-t irjon a fájlba"
|
||||
PythonFileReadline = "Olvas egy sort vagy 16 bájtig"
|
||||
PythonFileReadlines = "Olvas több sort"
|
||||
PythonFileTruncate = "A fájl átméretezése"
|
||||
PythonFileWritelines = "Irjon több sort"
|
||||
PythonFileName = "A fájl neve"
|
||||
PythonFileMode = "A fájl nyitott módja"
|
||||
PythonFileReadable = "read-et lehete használni"
|
||||
PythonFileWritable = "write-ot lehete használni"
|
||||
PythonImportOs = "os modul importálása"
|
||||
PythonOsUname = "Rendszer informaciók"
|
||||
PythonOsGetlogin = "Get username"
|
||||
PythonOsRemove = "Fájl törlése"
|
||||
PythonOsRename = "Fájl átnevezése"
|
||||
PythonOsListdir = "Fájlok listája"
|
||||
PythonImportSys = "sys modul importálása"
|
||||
PythonSysExit = "Terminate current program"
|
||||
PythonSysPrintexception = "Print exception"
|
||||
PythonSysByteorder = "The byte order of the system"
|
||||
PythonSysImplementation = "Information about Python"
|
||||
PythonSysModules = "Dictionary of loaded modules"
|
||||
PythonSysVersion = "Python language version (string)"
|
||||
PythonSysVersioninfo = "Python language version (tuple)"
|
||||
PythonPound = "Megjegyzés"
|
||||
PythonPercent = "Modulo"
|
||||
Python1J = "Képzeletbeli i"
|
||||
PythonLF = "Enter"
|
||||
PythonTab = "Táblázat"
|
||||
PythonAmpersand = "Logikus és"
|
||||
PythonSymbolExp = "logikus exkluzív vagy pedig"
|
||||
PythonVerticalBar = "logikus vagy pedig"
|
||||
PythonImag = "z képzeletbeli része"
|
||||
PythonReal = "z valódi része"
|
||||
PythonSingleQuote = "apostróf"
|
||||
PythonAbs = "Abszolút érték/nagyság"
|
||||
PythonAcos = "Ív (arc) koszinusz"
|
||||
PythonAcosh = "Hiperbolikus arc koszinusz"
|
||||
PythonAppend = "Lista végére hozzáadni x-et"
|
||||
PythonArrow = "(x,y) nyíla (x+dx,y+dy) nyílához"
|
||||
PythonAsin = "Ív (arc) szinusz"
|
||||
PythonAsinh = "Hiperbolikus ív (arc) szinusz"
|
||||
PythonAtan = "Ív (arc) érintö (tan)"
|
||||
PythonAtan2 = "atan(y/x) sámolása"
|
||||
PythonAtanh = "Hiperbolikus ív (arc) érintö (atan)"
|
||||
PythonAxis = "Tengelyeket (xmin,xmax,ymin,ymax)-ra állitani"
|
||||
PythonBar = "Az x lista oszlopdiagramja"
|
||||
PythonBin = "Egész szám konvertálása binárisra"
|
||||
PythonCeil = "Mennyezet"
|
||||
PythonChoice = "Véletlenszerü szám a listában"
|
||||
PythonClear = "A lista ürítése"
|
||||
PythonCmathFunction = "cmath modul funkció elötag"
|
||||
PythonColor = "Rgb (pzk) szín allítása"
|
||||
PythonColorBlack = "Fekete szín"
|
||||
PythonColorBlue = "Kék szín"
|
||||
PythonColorBrown = "Barna szín"
|
||||
PythonColorGreen = "Zöld szín"
|
||||
PythonColorGray = "Szürke szín"
|
||||
PythonColorOrange = "Narancssárga szín"
|
||||
PythonColorPink = "Rózsaszín szín"
|
||||
PythonColorPurple = "Lila szín"
|
||||
PythonColorRed = "Piros szín"
|
||||
PythonColorWhite = "Fehér szín"
|
||||
PythonColorYellow = "Sárga szín"
|
||||
PythonComplex = "A + ib visszaadása"
|
||||
PythonCopySign = "X visszaadása y jelével"
|
||||
PythonCos = "Koszinusz"
|
||||
PythonCosh = "Hiperbolikus koszinusz"
|
||||
PythonCount = "Számolja az x elöfordulását"
|
||||
PythonDegrees = "x konvertálása radiánokrol fokokra"
|
||||
PythonDivMod = "Hányados és maradék"
|
||||
PythonDrawCircle = "Rajzolj egy kört"
|
||||
PythonDrawLine = "Húzzon egy vonalat "
|
||||
PythonDrawString = "Szöveg megjelenítése (x, y)-en"
|
||||
PythonErf = "Hiba funkció"
|
||||
PythonErfc = "Kiegészítö hiba funkció"
|
||||
PythonEval = "Visszaadja az értékelt kifejezést"
|
||||
PythonExp = "Exponenciális függvény"
|
||||
PythonExpm1 = "exp(x)-1 sámitása"
|
||||
PythonFactorial = "x faktorál"
|
||||
PythonFabs = "Abszolút érték"
|
||||
PythonFillRect = "Téglalap töltése"
|
||||
PythonFillCircle = "Kitölti a kört"
|
||||
PythonFillPolygon = "Kitölti a poligont"
|
||||
PythonFloat = "Konvertálása tizedes számra"
|
||||
PythonFloor = "Egész része"
|
||||
PythonFmod = "a modulo b"
|
||||
PythonFrExp = "X mantissája és kiállítója"
|
||||
PythonGamma = "Gamma funkció"
|
||||
PythonGetKeys = "Billentyűk lenyomva"
|
||||
PythonGetPalette = "Téma paletta beszerzése"
|
||||
PythonGetPixel = "Visszatéríti (x,y) színét"
|
||||
PythonGetrandbits = "Váletlenszám visszatérítése k biten"
|
||||
PythonGrid = "Rács megjelenítése/elrejtése"
|
||||
PythonHex = "Decimális szám konvertálása hexadecimális számra"
|
||||
PythonHist = "x hisztográmiája"
|
||||
PythonImportCmath = "cmath modul importálása"
|
||||
PythonImportIon = "Ion modul importálása"
|
||||
PythonImportKandinsky = "Kandinsky modul importálása"
|
||||
PythonImportRandom = "Véletlenszerü modul importálása"
|
||||
PythonImportMath = "math modul importálása"
|
||||
PythonImportMatplotlibPyplot = "matplotlib.pyplot modul importálása"
|
||||
PythonImportNumpy = "ulab.numpy modul importálása"
|
||||
PythonImportScipy = "ulab.scipy modul importálása"
|
||||
PythonImportTurtle = "turtle modul importálása"
|
||||
PythonImportTime = "time modul importálása"
|
||||
PythonIndex = "Az elsö x esemény indexe"
|
||||
PythonInput = "Irjon egy értéket (számot)"
|
||||
PythonInsert = "x-et i. pozícióra helyezze a listában"
|
||||
PythonInt = "egész számra konvertálás"
|
||||
PythonIonFunction = "ion modul funkció elötag"
|
||||
PythonIsFinite = "x véges-e"
|
||||
PythonIsInfinite = "x végtelen-e"
|
||||
PythonIsKeyDown = "True-t válaszol ha a k gomb le van nyomva"
|
||||
PythonBattery = "Az akkumulátor feszültségének visszaadása"
|
||||
PythonBatteryLevel = "Az akkumulátor töltöttségi szintjének visszaadása"
|
||||
PythonBatteryIscharging = "Visszaadja, ha az akkumulátor töltődik"
|
||||
PythonSetBrightness = "Fényerőszint beállítása"
|
||||
PythonGetBrightness = "Get brightness level"
|
||||
PythonIsNaN = "Ellenörizze hogy x nem NaN"
|
||||
PythonKandinskyFunction = "kandinsky modul funkció elötag"
|
||||
PythonLdexp = "frexp ellentéte : x*(2**i)"
|
||||
PythonLength = "Egy targy hossza"
|
||||
PythonLgamma = "Gamma funkció logaritmusa"
|
||||
PythonLog = "a alapú logaritmus"
|
||||
PythonLog10 = "Decimális logaritmus"
|
||||
PythonLog2 = "Bináris logaritmus"
|
||||
PythonMathFunction = "math modul funkció elötag"
|
||||
PythonMatplotlibPyplotFunction = "matplotlib.pyplot elötag"
|
||||
PythonMax = "Maximum"
|
||||
PythonMin = "Minimum"
|
||||
PythonModf = "x-nek tört és egész részei"
|
||||
PythonMonotonic = "Az óra értékét adja vissza"
|
||||
PythonNumpyFunction = "numpy elötag"
|
||||
PythonNumpyFftFunction = "numpy.fft elötag"
|
||||
PythonNumpyLinalgFunction = "numpy.linalg elötag"
|
||||
PythonScipyFunction = "scipy elötag"
|
||||
PythonScipyLinalgFunction = "scipy.linalg elötag"
|
||||
PythonScipyOptimizeFunction = "scipy.optimize elötag"
|
||||
PythonScipySignalFunction = "scipy.signal elötag"
|
||||
PythonScipySpecialFunction = "scipy.special elötag"
|
||||
PythonOct = "Decimális szám konvertálása octális számra"
|
||||
PythonPhase = "z fázisa"
|
||||
PythonPlot = "y-t jelöli x függvényében"
|
||||
PythonPolar = "Verctorizálni"
|
||||
PythonPop = "Az utolsó elemet el törölni"
|
||||
PythonPower = "x y. kitevö"
|
||||
PythonPrint = "Ki irni a elemeket"
|
||||
PythonRadians = "Fokról radiánra konvertálni"
|
||||
PythonRandint = "Véletlen egész szám [a;b] -ban"
|
||||
PythonRandom = "Decimális szám [0;1] -ban"
|
||||
PythonRandomFunction = "random modul funkció elötag"
|
||||
PythonRandrange = "Véletlen szám range(start,stop)-ban"
|
||||
PythonRangeStartStop = "start-tol stop-ig listája"
|
||||
PythonRangeStop = "0 tol stop-ig lista"
|
||||
PythonRect = "Algebrai számra konvertálni"
|
||||
PythonRemove = "Elsö x elöfordulását törolni"
|
||||
PythonReverse = "A lista elemeit megfordítani (másik irány)"
|
||||
PythonRound = "N számjegyre kerekítni"
|
||||
PythonScatter = "(x,y) halmaza"
|
||||
PythonSeed = "Inicializálni a véletlenszám-választót"
|
||||
PythonSetPixel = "Az (x,y) pixel-t ki szinezni"
|
||||
PythonShow = "Mutassa az ábrát"
|
||||
PythonSin = "Szinusz"
|
||||
PythonSinh = "Hiperbolikus szinusz"
|
||||
PythonSleep = "t másodpercre meg állitani a programmot"
|
||||
PythonLocalTime = "Idő konvertálása csomóvá"
|
||||
PythonMktime = "A tuple konvertálása az időben"
|
||||
PythonTime = "Az aktuális időbélyeg letöltése"
|
||||
PythonSetLocaltime = "Idő beállítása egy csomóból"
|
||||
PythonRTCmode = "Aktuális RTC mód"
|
||||
PythonSetRTCmode = "RTC mód beállítása"
|
||||
PythonSort = "A listát rendezni"
|
||||
PythonSqrt = "Négyzetgyök"
|
||||
PythonSum = "Összeadni a lista elemeit"
|
||||
PythonTan = "Érintö (tan)"
|
||||
PythonTanh = "Hiperbolikus érintö (tan)"
|
||||
PythonText = "(x,y) nél egy szöveget irni"
|
||||
PythonTimeFunction = "time funkció elötag"
|
||||
PythonTrunc = "Egész csonka (?)"
|
||||
PythonTurtleBackward = "x pixelt hátra"
|
||||
PythonTurtleCircle = "r pixel sugarú kört rajzolni"
|
||||
PythonTurtleColor = "Toll szinét beállitani"
|
||||
PythonTurtleColorMode = "Szin módot 1.0-ra vagy 255-ra állitani"
|
||||
PythonTurtleForward = "x pixelt elölre"
|
||||
PythonTurtleFunction = "turtle modul funkció elötag"
|
||||
PythonTurtleGoto = "Menjen a (x,y) koordinátákra"
|
||||
PythonTurtleHeading = "Visszaadja az aktuális irányt"
|
||||
PythonTurtleHideturtle = "A teknös elrejtése"
|
||||
PythonTurtleIsdown = "True-t válaszol ha a toll irás pozícióban van"
|
||||
PythonTurtleLeft = "a fokkot forduljon balra"
|
||||
PythonTurtlePendown = "Húzza le a tollat"
|
||||
PythonTurtlePensize = "Állítsa a vonalvastagságot x pixelre"
|
||||
PythonTurtlePenup = "Húzza fel a tollat"
|
||||
PythonTurtlePosition = "Az aktuális (x,y) pozíciót visszaadása"
|
||||
PythonTurtleReset = "Visszaállitani a rajzot (torléssel)"
|
||||
PythonTurtleRight = "a fokkot forduljon jobbra"
|
||||
PythonTurtleSetheading = "a fokokra állítja be az irányt"
|
||||
PythonTurtleShowturtle = "A teknöst meg mutatni"
|
||||
PythonTurtleSpeed = "Rajzolási sebesség 0 és 10 között"
|
||||
PythonTurtleWrite = "Szöveg irás"
|
||||
PythonUniform = "Lebegöpontos szám [a,b] -ban"
|
||||
PythonImportTime = "time modul importálása"
|
||||
PythonMonotonic = "Meg fordítani a monoton idö"
|
||||
PythonFileOpen = "Fájl megnyitása"
|
||||
PythonFileSeekable = "Seek-et lehete használni"
|
||||
PythonFileSeek = "A kurzort áthelyezni"
|
||||
PythonFileTell = "Visszaadja a kurzor helye"
|
||||
PythonFileClose = "Bezárni egy fájlt"
|
||||
PythonFileClosed = "True ha a fájl bezárva"
|
||||
PythonFileRead = "Olvas 16 bájtig"
|
||||
PythonFileWrite = "b-t irjon a fájlba"
|
||||
PythonFileReadline = "Olvas egy sort vagy 16 bájtig"
|
||||
PythonFileReadlines = "Olvas több sort"
|
||||
PythonFileTruncate = "A fájl átméretezése"
|
||||
PythonFileWritelines = "Irjon több sort"
|
||||
PythonFileName = "A fájl neve"
|
||||
PythonFileMode = "A fájl nyitott módja"
|
||||
PythonFileReadable = "read-et lehete használni"
|
||||
PythonFileWritable = "write-ot lehete használni"
|
||||
PythonImportOs = "os modul importálása"
|
||||
PythonOsUname = "Rendszer informaciók"
|
||||
PythonOsGetlogin = "Get username"
|
||||
PythonOsRemove = "Fájl törlése"
|
||||
PythonOsRename = "Fájl átnevezése"
|
||||
PythonOsListdir = "Fájlok listája"
|
||||
PythonImportSys = "sys modul importálása"
|
||||
PythonSysExit = "Terminate current program"
|
||||
PythonSysPrintexception = "Print exception"
|
||||
PythonSysByteorder = "The byte order of the system"
|
||||
PythonSysImplementation = "Information about Python"
|
||||
PythonSysModules = "Dictionary of loaded modules"
|
||||
PythonSysVersion = "Python language version (string)"
|
||||
PythonSysVersioninfo = "Python language version (tuple)"
|
||||
|
||||
@@ -186,14 +186,11 @@ PythonTurtlePosition = "Fornisce posizione corrente (x,y)"
|
||||
PythonTurtleReset = "Azzera il disegno"
|
||||
PythonTurtleRight = "Ruota di a gradi a destra"
|
||||
PythonTurtleSetheading = "Imposta l'orientamento per a gradi"
|
||||
PythonTurtleSetposition = "Posiziona la tartaruga"
|
||||
PythonTurtleShowturtle = "Mostra la tartaruga"
|
||||
PythonTurtleSpeed = "Velocità di disegno (x tra 0 e 10)"
|
||||
PythonTurtleWrite = "Mostra un testo"
|
||||
PythonUniform = "Numero decimale tra [a,b]"
|
||||
PythonImportTime = "Import time module"
|
||||
PythonTimePrefix = "time module function prefix"
|
||||
PythonTimeSleep = "Wait for n second"
|
||||
PythonMonotonic = "Return monotonic time"
|
||||
PythonFileOpen = "Opens a file"
|
||||
PythonFileSeekable = "Tells if seek can be used on a file"
|
||||
|
||||
@@ -187,14 +187,11 @@ PythonTurtlePosition = "Zet huidige (x,y) locatie terug"
|
||||
PythonTurtleReset = "Reset de tekening"
|
||||
PythonTurtleRight = "Ga rechtsaf met a graden"
|
||||
PythonTurtleSetheading = "Zet de oriëntatie op a graden"
|
||||
PythonTurtleSetposition = "Plaats de schildpad"
|
||||
PythonTurtleShowturtle = "Laat de schildpad zien"
|
||||
PythonTurtleSpeed = "Tekensnelheid tussen 0 and 10"
|
||||
PythonTurtleWrite = "Display a text"
|
||||
PythonUniform = "Decimaal getal in [a,b]"
|
||||
PythonImportTime = "Import time module"
|
||||
PythonTimePrefix = "time module function prefix"
|
||||
PythonTimeSleep = "Wait for n second"
|
||||
PythonMonotonic = "Return monotonic time"
|
||||
PythonFileOpen = "Opens a file"
|
||||
PythonFileSeekable = "Tells if seek can be used on a file"
|
||||
|
||||
@@ -172,7 +172,6 @@ PythonTurtlePosition = "Devolve a posição atual (x,y)"
|
||||
PythonTurtleReset = "Reiniciar o desenho"
|
||||
PythonTurtleRight = "Virar à esquerda por a graus"
|
||||
PythonTurtleSetheading = "Definir a orientação por a graus"
|
||||
PythonTurtleSetposition = "Posicionamento da tartaruga"
|
||||
PythonTurtleShowturtle = "Mostrar o turtle"
|
||||
PythonTurtleSpeed = "Velocidade do desenho entre 0 e 10"
|
||||
PythonTurtleWrite = "Mostrar um texto"
|
||||
@@ -192,8 +191,6 @@ PythonSysImplementation = "Information about Python"
|
||||
PythonSysModules = "Dictionary of loaded modules"
|
||||
PythonSysVersion = "Python language version (string)"
|
||||
PythonSysVersioninfo = "Python language version (tuple)"
|
||||
PythonTimePrefix = "time module function prefix"
|
||||
PythonTimeSleep = "Wait for n second"
|
||||
PythonMonotonic = "Return monotonic time"
|
||||
PythonFileOpen = "Opens a file"
|
||||
PythonFileSeekable = "Tells if seek can be used on a file"
|
||||
|
||||
@@ -114,52 +114,6 @@ PythonCommandIsInfinite = "isinf(x)"
|
||||
PythonCommandIsNaN = "isnan(x)"
|
||||
PythonCommandKandinskyFunction = "kandinsky.function"
|
||||
PythonCommandKandinskyFunctionWithoutArg = "kandinsky.\x11"
|
||||
PythonCommandKeyLeft = "KEY_LEFT"
|
||||
PythonCommandKeyUp = "KEY_UP"
|
||||
PythonCommandKeyDown = "KEY_DOWN"
|
||||
PythonCommandKeyRight = "KEY_RIGHT"
|
||||
PythonCommandKeyOk = "KEY_OK"
|
||||
PythonCommandKeyBack = "KEY_BACK"
|
||||
PythonCommandKeyHome = "KEY_HOME"
|
||||
PythonCommandKeyOnOff = "KEY_ONOFF"
|
||||
PythonCommandKeyShift = "KEY_SHIFT"
|
||||
PythonCommandKeyAlpha = "KEY_ALPHA"
|
||||
PythonCommandKeyXnt = "KEY_XNT"
|
||||
PythonCommandKeyVar = "KEY_VAR"
|
||||
PythonCommandKeyToolbox = "KEY_TOOLBOX"
|
||||
PythonCommandKeyBackspace = "KEY_BACKSPACE"
|
||||
PythonCommandKeyExp = "KEY_EXP"
|
||||
PythonCommandKeyLn = "KEY_LN"
|
||||
PythonCommandKeyLog = "KEY_LOG"
|
||||
PythonCommandKeyImaginary = "KEY_IMAGINARY"
|
||||
PythonCommandKeyComma = "KEY_COMMA"
|
||||
PythonCommandKeyPower = "KEY_POWER"
|
||||
PythonCommandKeySine = "KEY_SINE"
|
||||
PythonCommandKeyCosine = "KEY_COSINE"
|
||||
PythonCommandKeyTangent = "KEY_TANGENT"
|
||||
PythonCommandKeyPi = "KEY_PI"
|
||||
PythonCommandKeySqrt = "KEY_SQRT"
|
||||
PythonCommandKeySquare = "KEY_SQUARE"
|
||||
PythonCommandKeySeven = "KEY_SEVEN"
|
||||
PythonCommandKeyEight = "KEY_EIGHT"
|
||||
PythonCommandKeyNine = "KEY_NINE"
|
||||
PythonCommandKeyLeftParenthesis = "KEY_LEFTPARENTHESIS"
|
||||
PythonCommandKeyRightParenthesis = "KEY_RIGHTPARENTHESIS"
|
||||
PythonCommandKeyFour = "KEY_FOUR"
|
||||
PythonCommandKeyFive = "KEY_FIVE"
|
||||
PythonCommandKeySix = "KEY_SIX"
|
||||
PythonCommandKeyMultiplication = "KEY_MULTIPLICATION"
|
||||
PythonCommandKeyDivision = "KEY_DIVISION"
|
||||
PythonCommandKeyOne = "KEY_ONE"
|
||||
PythonCommandKeyTwo = "KEY_TWO"
|
||||
PythonCommandKeyThree = "KEY_THREE"
|
||||
PythonCommandKeyPlus = "KEY_PLUS"
|
||||
PythonCommandKeyMinus = "KEY_MINUS"
|
||||
PythonCommandKeyZero = "KEY_ZERO"
|
||||
PythonCommandKeyDot = "KEY_DOT"
|
||||
PythonCommandKeyEe = "KEY_EE"
|
||||
PythonCommandKeyAns = "KEY_ANS"
|
||||
PythonCommandKeyExe = "KEY_EXE"
|
||||
PythonCommandIsKeyDown = "keydown(k)"
|
||||
PythonCommandBattery = "battery()"
|
||||
PythonCommandBatteryLevel = "battery_level()"
|
||||
@@ -403,16 +357,8 @@ PythonTurtleCommandPosition = "position()"
|
||||
PythonTurtleCommandReset = "reset()"
|
||||
PythonTurtleCommandRight = "right(a)"
|
||||
PythonTurtleCommandSetheading = "setheading(a)"
|
||||
PythonTurtleCommandSetposition = "setposition(x,[y])"
|
||||
PythonTurtleCommandShowturtle = "showturtle()"
|
||||
PythonTurtleCommandSpeed = "speed(x)"
|
||||
PythonTurtleCommandWhite = "'white'"
|
||||
PythonTurtleCommandYellow = "'yellow'"
|
||||
PythonTimeModule = "time"
|
||||
PythonTimeCommandImportFrom = "from time import *"
|
||||
PythonTimeCommandSleep = "sleep()"
|
||||
PythonTimeCommandSleepDemo = "sleep(n)"
|
||||
PythonTimeCommandMonotonic = "monotonic()"
|
||||
PythonCommandFileOpen = "open(name, [mode])"
|
||||
PythonCommandFileOpenWithoutArg = "open(\x11)"
|
||||
PythonCommandFileSeek = "file.seek(offset, [whence])"
|
||||
|
||||
@@ -26,7 +26,9 @@ void EditorView::resetSelection() {
|
||||
}
|
||||
|
||||
void EditorView::scrollViewDidChangeOffset(ScrollViewDataSource * scrollViewDataSource) {
|
||||
m_gutterView.setOffset(scrollViewDataSource->offset().y());
|
||||
if (m_gutterView.setOffsetAndNeedResize(scrollViewDataSource->offset().y())) {
|
||||
internalLayoutSubviews(true);
|
||||
}
|
||||
}
|
||||
|
||||
View * EditorView::subviewAtIndex(int index) {
|
||||
@@ -42,8 +44,12 @@ void EditorView::didBecomeFirstResponder() {
|
||||
}
|
||||
|
||||
void EditorView::layoutSubviews(bool force) {
|
||||
m_gutterView.setOffset(0);
|
||||
KDCoordinate gutterWidth = m_gutterView.minimalSizeForOptimalDisplay().width();
|
||||
m_gutterView.setOffsetAndNeedResize(0); // Whatever the return is, we layout the editor view
|
||||
internalLayoutSubviews(force);
|
||||
}
|
||||
|
||||
void EditorView::internalLayoutSubviews(bool force) {
|
||||
KDCoordinate gutterWidth = m_gutterView.computeWidth();
|
||||
m_gutterView.setFrame(KDRect(0, 0, gutterWidth, bounds().height()), force);
|
||||
|
||||
m_textArea.setFrame(KDRect(
|
||||
@@ -67,23 +73,23 @@ void EditorView::GutterView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
KDCoordinate firstLine = m_offset / glyphSize.height();
|
||||
KDCoordinate firstLinePixelOffset = m_offset - firstLine * glyphSize.height();
|
||||
|
||||
char lineNumber[k_lineNumberCharLength];
|
||||
char lineNumberBuffer[m_numberOfDigits + 1];
|
||||
int numberOfLines = bounds().height() / glyphSize.height() + 1;
|
||||
for (int i=0; i<numberOfLines; i++) {
|
||||
// Only the first two digits are displayed
|
||||
int lineNumberValue = (i + firstLine + 1) % 100;
|
||||
int lineNumberValue = (i + firstLine + 1);
|
||||
Poincare::Integer line(lineNumberValue);
|
||||
if (firstLine < 10 || lineNumberValue >= 10) {
|
||||
line.serialize(lineNumber, k_lineNumberCharLength);
|
||||
} else {
|
||||
// Add a leading "0"
|
||||
lineNumber[0] = '0';
|
||||
line.serialize(lineNumber + 1, k_lineNumberCharLength - 1);
|
||||
|
||||
int lineDigits = computeNumberOfDigitsFor(lineNumberValue);
|
||||
|
||||
for (int j=0; j < m_numberOfDigits - lineDigits; j++) {
|
||||
lineNumberBuffer[j] = ' ';
|
||||
}
|
||||
KDCoordinate leftPadding = (2 - strlen(lineNumber)) * glyphSize.width();
|
||||
|
||||
line.serialize(lineNumberBuffer + (m_numberOfDigits - lineDigits), m_numberOfDigits + 1);
|
||||
|
||||
ctx->drawString(
|
||||
lineNumber,
|
||||
KDPoint(k_margin + leftPadding, i*glyphSize.height() - firstLinePixelOffset),
|
||||
lineNumberBuffer,
|
||||
KDPoint(k_margin, i*glyphSize.height() - firstLinePixelOffset),
|
||||
m_font,
|
||||
textColor,
|
||||
backgroundColor
|
||||
@@ -91,18 +97,36 @@ void EditorView::GutterView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
}
|
||||
}
|
||||
|
||||
void EditorView::GutterView::setOffset(KDCoordinate offset) {
|
||||
bool EditorView::GutterView::setOffsetAndNeedResize(KDCoordinate offset) {
|
||||
if (m_offset == offset) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
m_offset = offset;
|
||||
|
||||
int numberOfDigits = computeMaxNumberOfDigits();
|
||||
if (numberOfDigits != m_numberOfDigits) {
|
||||
m_numberOfDigits = numberOfDigits;
|
||||
return true;
|
||||
}
|
||||
|
||||
markRectAsDirty(bounds());
|
||||
return false;
|
||||
}
|
||||
|
||||
int EditorView::GutterView::computeWidth() {
|
||||
return 2 * k_margin + (m_numberOfDigits) * m_font->glyphSize().width();
|
||||
}
|
||||
|
||||
KDSize EditorView::GutterView::minimalSizeForOptimalDisplay() const {
|
||||
int numberOfChars = 2; // TODO: Could be computed
|
||||
return KDSize(2 * k_margin + numberOfChars * m_font->glyphSize().width(), 0);
|
||||
int EditorView::GutterView::computeMaxNumberOfDigits() {
|
||||
return computeNumberOfDigitsFor((bounds().height() / m_font->glyphSize().height() + 1) + (m_offset / m_font->glyphSize().height()));
|
||||
}
|
||||
|
||||
int EditorView::GutterView::computeNumberOfDigitsFor(int value) {
|
||||
int digits = 1;
|
||||
while (value >= pow(10, digits)) {
|
||||
digits++;
|
||||
}
|
||||
return digits;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ public:
|
||||
void unloadSyntaxHighlighter() { m_textArea.unloadSyntaxHighlighter(); };
|
||||
void scrollViewDidChangeOffset(ScrollViewDataSource * scrollViewDataSource) override;
|
||||
void didBecomeFirstResponder() override;
|
||||
void internalLayoutSubviews(bool force);
|
||||
private:
|
||||
int numberOfSubviews() const override { return 2; }
|
||||
View * subviewAtIndex(int index) override;
|
||||
@@ -36,15 +37,21 @@ private:
|
||||
|
||||
class GutterView : public View {
|
||||
public:
|
||||
GutterView(const KDFont * font) : View(), m_font(font), m_offset(0) {}
|
||||
GutterView(const KDFont * font) : View(), m_font(font), m_offset(0), m_numberOfDigits(2) {}
|
||||
|
||||
void drawRect(KDContext * ctx, KDRect rect) const override;
|
||||
void setOffset(KDCoordinate offset);
|
||||
KDSize minimalSizeForOptimalDisplay() const override;
|
||||
bool setOffsetAndNeedResize(KDCoordinate offset); // Return true if the gutter view need to be resized
|
||||
|
||||
int computeWidth();
|
||||
int computeMaxNumberOfDigits();
|
||||
static int computeNumberOfDigitsFor(int value);
|
||||
|
||||
private:
|
||||
static constexpr KDCoordinate k_margin = 2;
|
||||
static constexpr int k_lineNumberCharLength = 3;
|
||||
|
||||
const KDFont * m_font;
|
||||
KDCoordinate m_offset;
|
||||
int m_numberOfDigits;
|
||||
};
|
||||
|
||||
PythonTextArea m_textArea;
|
||||
|
||||
@@ -41,6 +41,25 @@ void GlobalPreferences::setBrightnessLevel(int brightnessLevel) {
|
||||
brightnessLevel = brightnessLevel < 0 ? 0 : brightnessLevel;
|
||||
brightnessLevel = brightnessLevel > Ion::Backlight::MaxBrightness ? Ion::Backlight::MaxBrightness : brightnessLevel;
|
||||
m_brightnessLevel = brightnessLevel;
|
||||
Ion::Backlight::setBrightness(m_brightnessLevel);
|
||||
}
|
||||
}
|
||||
|
||||
void GlobalPreferences::setIdleBeforeSuspendSeconds(int idleBeforeSuspendSeconds) {
|
||||
if (m_idleBeforeSuspendSeconds != idleBeforeSuspendSeconds) {
|
||||
idleBeforeSuspendSeconds = idleBeforeSuspendSeconds < 5 ? 5 : idleBeforeSuspendSeconds;
|
||||
idleBeforeSuspendSeconds = idleBeforeSuspendSeconds > 7200 ? 7200 : idleBeforeSuspendSeconds;
|
||||
m_idleBeforeSuspendSeconds = idleBeforeSuspendSeconds;
|
||||
}
|
||||
}
|
||||
|
||||
void GlobalPreferences::setIdleBeforeDimmingSeconds(int idleBeforeDimmingSeconds) {
|
||||
if (m_idleBeforeDimmingSeconds != idleBeforeDimmingSeconds) {
|
||||
idleBeforeDimmingSeconds = idleBeforeDimmingSeconds < 3 ? 3 : idleBeforeDimmingSeconds;
|
||||
idleBeforeDimmingSeconds = idleBeforeDimmingSeconds > 1200 ? 1200 : idleBeforeDimmingSeconds;
|
||||
m_idleBeforeDimmingSeconds = idleBeforeDimmingSeconds;
|
||||
}
|
||||
}
|
||||
|
||||
void GlobalPreferences::setBrightnessShortcut(int brightnessShortcut){
|
||||
m_brightnessShortcut = brightnessShortcut;
|
||||
}
|
||||
|
||||
@@ -45,6 +45,12 @@ public:
|
||||
const KDFont * font() const { return m_font; }
|
||||
void setFont(const KDFont * font) { m_font = font; }
|
||||
constexpr static int NumberOfBrightnessStates = 15;
|
||||
int idleBeforeSuspendSeconds() const { return m_idleBeforeSuspendSeconds; }
|
||||
void setIdleBeforeSuspendSeconds(int m_idleBeforeSuspendSeconds);
|
||||
int idleBeforeDimmingSeconds() const { return m_idleBeforeDimmingSeconds; }
|
||||
void setIdleBeforeDimmingSeconds(int m_idleBeforeDimmingSeconds);
|
||||
int brightnessShortcut() const { return m_brightnessShortcut; }
|
||||
void setBrightnessShortcut(int m_BrightnessShortcut);
|
||||
private:
|
||||
static_assert(I18n::NumberOfLanguages > 0, "I18n::NumberOfLanguages is not superior to 0"); // There should already have been an error when processing an empty EPSILON_I18N flag
|
||||
static_assert(I18n::NumberOfCountries > 0, "I18n::NumberOfCountries is not superior to 0"); // There should already have been an error when processing an empty EPSILON_COUNTRIES flag
|
||||
@@ -60,6 +66,9 @@ private:
|
||||
m_syntaxhighlighting(true),
|
||||
m_cursorSaving(true),
|
||||
m_brightnessLevel(Ion::Backlight::MaxBrightness),
|
||||
m_idleBeforeSuspendSeconds(55),
|
||||
m_idleBeforeDimmingSeconds(45),
|
||||
m_brightnessShortcut(4),
|
||||
m_font(KDFont::LargeFont) {}
|
||||
I18n::Language m_language;
|
||||
I18n::Country m_country;
|
||||
@@ -74,6 +83,9 @@ private:
|
||||
bool m_syntaxhighlighting;
|
||||
bool m_cursorSaving;
|
||||
int m_brightnessLevel;
|
||||
int m_idleBeforeSuspendSeconds;
|
||||
int m_idleBeforeDimmingSeconds;
|
||||
int m_brightnessShortcut;
|
||||
const KDFont * m_font;
|
||||
};
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ bool ListParameterController::handleEvent(Ion::Events::Event event) {
|
||||
}
|
||||
if (event == Ion::Events::Right) {
|
||||
int selectedR = selectedRow();
|
||||
if (selectedR == 0 || selectedR == 1) {
|
||||
if (selectedR == 0 || selectedR == 1 || selectedR == 3) {
|
||||
// Go in the submenu
|
||||
return handleEnterOnRow(selectedR);
|
||||
}
|
||||
|
||||
@@ -5,40 +5,42 @@ namespace Reader {
|
||||
|
||||
// List of available Symbols
|
||||
static constexpr char const * k_SymbolsCommands[] = {
|
||||
"times", "div", "forall", "partial", "exists", "pm", "approx", "infty", "neq", "equiv", "leq", "geq",
|
||||
"leftarrow", "uparrow", "rightarrow", "downarrow", "leftrightarrow", "updownarrow", "Leftarrow", "Uparrow", "Rightarrow", "Downarrow",
|
||||
"Alpha", "Beta", "Gamma", "Delta", "Epsilon", "Zeta", "Eta", "Theta", "Iota", "Kappa", "Lambda",
|
||||
"times", "div", "forall", "partial", "exists", "pm", "approx", "infty", "neq", "equiv", "leq", "geq",
|
||||
"leftarrow", "uparrow", "rightarrow", "downarrow","leftrightarrow", "updownarrow", "Leftarrow", "Uparrow", "Rightarrow", "Downarrow",
|
||||
"nwarrow", "nearrow", "swarrow", "searrow", "in", "cdot", "cdots", "ldots",
|
||||
"Alpha", "Beta", "Gamma", "Delta", "Epsilon", "Zeta", "Eta", "Theta", "Iota", "Kappa", "Lambda",
|
||||
"Mu", "Nu", "Xi", "Omicron", "Pi", "Rho", "Sigma", "Tau", "Upsilon", "Phi", "Chi", "Psi","Omega",
|
||||
"alpha", "beta", "gamma", "delta", "epsilon", "zeta", "eta", "theta", "iota", "kappa", "lambda",
|
||||
"alpha", "beta", "gamma", "delta", "epsilon", "zeta", "eta", "theta", "iota", "kappa", "lambda",
|
||||
"mu", "nu", "xi", "omicron", "pi", "rho", "sigma", "tau", "upsilon", "phi", "chi", "psi", "omega",
|
||||
"sim",
|
||||
};
|
||||
|
||||
// List of the available Symbol's CodePoints in the same order of the Symbol's list
|
||||
static constexpr uint32_t const k_SymbolsCodePoints[] = {
|
||||
0xd7, 0xf7, 0x2200, 0x2202, 0x2203, 0xb1, 0x2248, 0x221e, 0x2260, 0x2261, 0x2264, 0x2265,
|
||||
0x2190, 0x2191, 0x2192, 0x2193, 0x2194, 0x2195, 0x21d0, 0x21d1, 0x21d2, 0x21d3,
|
||||
0x391, 0x392, 0x393, 0x394, 0x395, 0x396, 0x397, 0x398, 0x399, 0x39a, 0x39b,
|
||||
0x39c, 0x39d, 0x39e, 0x39f, 0x3a0, 0x3a1, 0x3a3, 0x3a4, 0x3a5, 0x3a6, 0x3a7, 0x3a8, 0x3a9,
|
||||
0x3b1, 0x3b2, 0x3b3, 0x3b4, 0x3b5, 0x3b6, 0x3b7, 0x3b8, 0x3b9, 0x3ba, 0x3bb,
|
||||
0xd7, 0xf7, 0x2200, 0x2202, 0x2203, 0xb1, 0x2248, 0x221e, 0x2260, 0x2261, 0x2264, 0x2265,
|
||||
0x2190, 0x2191, 0x2192, 0x2193, 0x2194, 0x2195, 0x21d0, 0x21d1, 0x21d2, 0x21d3,
|
||||
0x2196, 0x2197, 0x2198, 0x2199, 0x454, 0xb7, 0x2505, 0x2026,
|
||||
0x391, 0x392, 0x393, 0x394, 0x395, 0x396, 0x397, 0x398, 0x399, 0x39a, 0x39b,
|
||||
0x39c, 0x39d, 0x39e, 0x39f, 0x3a0, 0x3a1, 0x3a3, 0x3a4, 0x3a5, 0x3a6, 0x3a7, 0x3a8, 0x3a9,
|
||||
0x3b1, 0x3b2, 0x3b3, 0x3b4, 0x3b5, 0x3b6, 0x3b7, 0x3b8, 0x3b9, 0x3ba, 0x3bb,
|
||||
0x3bc, 0x3bd, 0x3be, 0x3bf, 0x3c0, 0x3c1, 0x3c3, 0x3c4, 0x3c5, 0x3c6, 0x3c7, 0x3c8, 0x3c9,
|
||||
0x7e,
|
||||
};
|
||||
|
||||
|
||||
// List of available Function Commands that don't require a specific handling
|
||||
static constexpr char const * k_FunctionCommands[] = {
|
||||
"arccos", "arcsin", "arctan", "arg", "cos", "cosh", "cot", "coth",
|
||||
"csc", "deg", "det", "dim", "exp", "gcd", "hom", "inf",
|
||||
"ker", "lg", "lim", "liminf", "limsup", "ln", "log", "max",
|
||||
"arccos", "arcsin", "arctan", "arg", "cos", "cosh", "cot", "coth",
|
||||
"csc", "deg", "det", "dim", "exp", "gcd", "hom", "inf",
|
||||
"ker", "lg", "lim", "liminf", "limsup", "ln", "log", "max",
|
||||
"min", "Pr", "sec", "sin", "sinh", "sup", "tan", "tanh"
|
||||
};
|
||||
|
||||
TexParser::TexParser(const char * text, const char * endOfText) :
|
||||
m_text(text),
|
||||
TexParser::TexParser(const char * text, const char * endOfText) :
|
||||
m_text(text),
|
||||
m_endOfText(endOfText),
|
||||
m_hasError(false)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
Layout TexParser::getLayout() {
|
||||
@@ -78,7 +80,7 @@ Layout TexParser::popBlock() {
|
||||
Layout TexParser::popText(char stop) {
|
||||
HorizontalLayout layout = HorizontalLayout::Builder();
|
||||
const char * start = m_text;
|
||||
|
||||
|
||||
while (m_text < m_endOfText && *m_text != stop) {
|
||||
switch (*m_text) {
|
||||
// TODO: Factorize this code
|
||||
@@ -121,7 +123,7 @@ Layout TexParser::popText(char stop) {
|
||||
if (start != m_text) {
|
||||
layout.addOrMergeChildAtIndex(LayoutHelper::String(start, m_text - start), layout.numberOfChildren(), false);
|
||||
}
|
||||
|
||||
|
||||
m_text ++;
|
||||
|
||||
if (layout.numberOfChildren() == 1) {
|
||||
@@ -149,7 +151,7 @@ Layout TexParser::popCommand() {
|
||||
if (isCommandEnded(*(m_text + strlen(k_fracCommand)))) {
|
||||
m_text += strlen(k_fracCommand);
|
||||
return popFracCommand();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (strncmp(k_leftCommand, m_text, strlen(k_leftCommand)) == 0) {
|
||||
if (isCommandEnded(*(m_text + strlen(k_leftCommand)))) {
|
||||
@@ -199,20 +201,20 @@ Layout TexParser::popCommand() {
|
||||
return LayoutHelper::String(k_FunctionCommands[i], strlen(k_FunctionCommands[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_hasError = true;
|
||||
m_hasError = true;
|
||||
return EmptyLayout::Builder();
|
||||
}
|
||||
|
||||
// Expressions
|
||||
Layout TexParser::popCeilCommand() {
|
||||
Layout ceil = popBlock();
|
||||
Layout ceil = popBlock();
|
||||
return CeilingLayout::Builder(ceil);
|
||||
}
|
||||
|
||||
Layout TexParser::popFloorCommand() {
|
||||
Layout floor = popBlock();
|
||||
Layout floor = popBlock();
|
||||
return FloorLayout::Builder(floor);
|
||||
}
|
||||
|
||||
@@ -255,7 +257,7 @@ Layout TexParser::popSpaceCommand() {
|
||||
Layout TexParser::popOverrightarrowCommand() {
|
||||
return VectorLayout::Builder(popBlock());
|
||||
}
|
||||
|
||||
|
||||
Layout TexParser::popSymbolCommand(int SymbolIndex) {
|
||||
uint32_t codePoint = k_SymbolsCodePoints[SymbolIndex];
|
||||
return CodePointLayout::Builder(codePoint);
|
||||
|
||||
@@ -17,6 +17,5 @@ NEnd = "Endwert"
|
||||
TermSum = "Summe der Terme"
|
||||
SelectFirstTerm = "Erster Term "
|
||||
SelectLastTerm = "Letzter Term "
|
||||
ValueNotReachedBySequence = "Wert wird von Folge nicht erreicht"
|
||||
NColumn = "n-te Spalte"
|
||||
FirstTermIndex = "Anfangsindex"
|
||||
|
||||
@@ -17,6 +17,5 @@ NEnd = "N end"
|
||||
TermSum = "Sum of terms"
|
||||
SelectFirstTerm = "Select First Term "
|
||||
SelectLastTerm = "Select last term "
|
||||
ValueNotReachedBySequence = "Value not reached by sequence"
|
||||
NColumn = "n column"
|
||||
FirstTermIndex = "First term index"
|
||||
|
||||
@@ -17,6 +17,5 @@ NEnd = "N fin"
|
||||
TermSum = "Suma de términos"
|
||||
SelectFirstTerm = "Seleccionar el primer término "
|
||||
SelectLastTerm = "Seleccionar el último término "
|
||||
ValueNotReachedBySequence = "No se alcanza este valor"
|
||||
NColumn = "Columna n"
|
||||
FirstTermIndex = "Índice del primer término"
|
||||
|
||||
@@ -17,6 +17,5 @@ NEnd = "N fin"
|
||||
TermSum = "Somme des termes"
|
||||
SelectFirstTerm = "Sélectionner le premier terme "
|
||||
SelectLastTerm = "Sélectionner le dernier terme "
|
||||
ValueNotReachedBySequence = "Valeur non atteinte par la suite"
|
||||
NColumn = "Colonne n"
|
||||
FirstTermIndex = "Indice premier terme"
|
||||
|
||||
@@ -1,22 +1,21 @@
|
||||
SequenceApp = "Szekvenciák"
|
||||
SequenceAppCapital = "SZEKVENCIÁK"
|
||||
SequenceTab = "Szekvenciák"
|
||||
AddSequence = "Szekvencia hozzáadása"
|
||||
ChooseSequenceType = "Válassza ki a sorozat típusát"
|
||||
SequenceType = "Szekvencia típusa"
|
||||
Explicit = "Explicit kifejezés"
|
||||
SingleRecurrence = "Rekurzív elsö sorrend"
|
||||
DoubleRecurrence = "Rekurzív második sorrend"
|
||||
SequenceOptions = "Szekvencia opciók"
|
||||
SequenceColor = "Szekvencia színe"
|
||||
DeleteSequence = "Sorozat törlése"
|
||||
NoSequence = "Nincs sorrend"
|
||||
NoActivatedSequence = "Nincs szekvencia bekapcsolva"
|
||||
NStart = "N start"
|
||||
NEnd = "N vég"
|
||||
TermSum = "A kifejezés összege"
|
||||
SelectFirstTerm = "Elsö kifejezés kiválasztása "
|
||||
SelectLastTerm = "Utolsó kifejezés kiválasztása "
|
||||
ValueNotReachedBySequence = "Az értéket nem érte el a sorozat"
|
||||
NColumn = "n oszlop"
|
||||
FirstTermIndex = "Elsö kifejezés index"
|
||||
SequenceApp = "Szekvenciák"
|
||||
SequenceAppCapital = "SZEKVENCIÁK"
|
||||
SequenceTab = "Szekvenciák"
|
||||
AddSequence = "Szekvencia hozzáadása"
|
||||
ChooseSequenceType = "Válassza ki a sorozat típusát"
|
||||
SequenceType = "Szekvencia típusa"
|
||||
Explicit = "Explicit kifejezés"
|
||||
SingleRecurrence = "Rekurzív elsö sorrend"
|
||||
DoubleRecurrence = "Rekurzív második sorrend"
|
||||
SequenceOptions = "Szekvencia opciók"
|
||||
SequenceColor = "Szekvencia színe"
|
||||
DeleteSequence = "Sorozat törlése"
|
||||
NoSequence = "Nincs sorrend"
|
||||
NoActivatedSequence = "Nincs szekvencia bekapcsolva"
|
||||
NStart = "N start"
|
||||
NEnd = "N vég"
|
||||
TermSum = "A kifejezés összege"
|
||||
SelectFirstTerm = "Elsö kifejezés kiválasztása "
|
||||
SelectLastTerm = "Utolsó kifejezés kiválasztása "
|
||||
NColumn = "n oszlop"
|
||||
FirstTermIndex = "Elsö kifejezés index"
|
||||
|
||||
@@ -17,6 +17,5 @@ NEnd = "N finale"
|
||||
TermSum = "Somma dei termini"
|
||||
SelectFirstTerm = "Selezionare il primo termine "
|
||||
SelectLastTerm = "Selezionare l'ultimo termine "
|
||||
ValueNotReachedBySequence = "Valore non raggiunto dalla successione"
|
||||
NColumn = "Colonna n"
|
||||
FirstTermIndex = "Indice del primo termine"
|
||||
|
||||
@@ -17,6 +17,5 @@ NEnd = "N einde"
|
||||
TermSum = "Som van termen"
|
||||
SelectFirstTerm = "Selecteer eerste term "
|
||||
SelectLastTerm = "Selecteer laatste term "
|
||||
ValueNotReachedBySequence = "Waarde niet bereikt door de rij"
|
||||
NColumn = "n-kolom"
|
||||
FirstTermIndex = "Eerste termindex"
|
||||
|
||||
@@ -17,6 +17,5 @@ NEnd = "N fim"
|
||||
TermSum = "Soma dos termos"
|
||||
SelectFirstTerm = "Selecionar primeiro termo "
|
||||
SelectLastTerm = "Selecionar último termo "
|
||||
ValueNotReachedBySequence = "O valor não é alcançado pela sequência"
|
||||
NColumn = "Coluna n"
|
||||
FirstTermIndex = "Índice do primeiro termo"
|
||||
|
||||
@@ -24,38 +24,18 @@ const char * ListParameterController::title() {
|
||||
|
||||
bool ListParameterController::handleEvent(Ion::Events::Event event) {
|
||||
bool hasAdditionalRow = hasInitialRankRow();
|
||||
#if FUNCTION_COLOR_CHOICE
|
||||
if (event == Ion::Events::OK || event == Ion::Events::EXE || (event == Ion::Events::Right && selectedRow() == 1)) {
|
||||
#else
|
||||
if (event == Ion::Events::OK || event == Ion::Events::EXE || (event == Ion::Events::Right && selectedRow() == 0)) {
|
||||
#endif
|
||||
int selectedRowIndex = selectedRow();
|
||||
#if FUNCTION_COLOR_CHOICE
|
||||
if (selectedRowIndex == 0) {
|
||||
return handleEnterOnRow(selectedRowIndex);
|
||||
}
|
||||
if (selectedRowIndex == 1) {
|
||||
#else
|
||||
if (selectedRowIndex == 0) {
|
||||
#endif
|
||||
StackViewController * stack = (StackViewController *)(parentResponder());
|
||||
m_typeParameterController.setRecord(m_record);
|
||||
stack->push(&m_typeParameterController);
|
||||
return true;
|
||||
}
|
||||
#if FUNCTION_COLOR_CHOICE
|
||||
if (selectedRowIndex == 2+hasAdditionalRow) {
|
||||
|
||||
#else
|
||||
if (selectedRowIndex == 1+hasAdditionalRow) {
|
||||
#endif
|
||||
if (selectedRowIndex == 1+hasAdditionalRow || selectedRowIndex == 2+hasAdditionalRow) {
|
||||
return handleEnterOnRow(selectedRowIndex-hasAdditionalRow-1);
|
||||
}
|
||||
#if FUNCTION_COLOR_CHOICE
|
||||
if (selectedRowIndex == 3+hasAdditionalRow) {
|
||||
#else
|
||||
if (selectedRowIndex == 2+hasAdditionalRow) {
|
||||
#endif
|
||||
App::app()->localContext()->resetCache();
|
||||
return handleEnterOnRow(selectedRowIndex-hasAdditionalRow-1);
|
||||
}
|
||||
|
||||
@@ -25,11 +25,7 @@ public:
|
||||
HighlightCell * reusableCell(int index, int type) override;
|
||||
void willDisplayCellForIndex(HighlightCell * cell, int index) override;
|
||||
private:
|
||||
#if FUNCTION_COLOR_CHOICE
|
||||
constexpr static int k_totalNumberOfCell = 5;
|
||||
#else
|
||||
constexpr static int k_totalNumberOfCell = 4;
|
||||
#endif
|
||||
int totalNumberOfCells() const override;
|
||||
Shared::Sequence * sequence() { return static_cast<Shared::Sequence *>(function().pointer()); }
|
||||
bool hasInitialRankRow() const;
|
||||
|
||||
@@ -26,6 +26,7 @@ app_settings_src = $(addprefix apps/settings/,\
|
||||
sub_menu/math_options_controller.cpp \
|
||||
sub_menu/selectable_view_with_messages.cpp \
|
||||
sub_menu/usb_protection_controller.cpp \
|
||||
sub_menu/brightness_controller.cpp\
|
||||
)
|
||||
|
||||
SFLAGS += -DOMEGA_STATE="$(OMEGA_STATE)"
|
||||
|
||||
@@ -32,6 +32,7 @@ Real = "Reell "
|
||||
Cartesian = "Kartesisch "
|
||||
Polar = "Polar "
|
||||
Brightness = "Helligkeit"
|
||||
BrightnessSettings = "Helligkeitseinstellungen"
|
||||
SoftwareVersion = "Epsilon version"
|
||||
UpsilonVersion = "Upsilon version"
|
||||
OmegaVersion = "Omega version"
|
||||
@@ -62,7 +63,6 @@ SymbolFunction = "Ausdrucksformat "
|
||||
SymbolDefaultFunction = "Standardl "
|
||||
SymbolArgFunction = "Leer "
|
||||
SymbolArgDefaultFunction = "Argument "
|
||||
PythonFont = "Python Schriftart"
|
||||
MemUse = "Speicher"
|
||||
DateTime = "Datum/Uhrzeit"
|
||||
ActivateClock = "Uhr aktivieren"
|
||||
@@ -80,3 +80,7 @@ USBProtectionLevel = "Akzeptierte Updates"
|
||||
USBDefaultLevel = "Basierend auf Upsilon"
|
||||
USBLowLevel = "Basierend auf Omega"
|
||||
USBParanoidLevel = "Nichts"
|
||||
Normal = "Normal"
|
||||
IdleTimeBeforeDimming = "Abdunkeln nach (s)"
|
||||
IdleTimeBeforeSuspend = "Anhalten nach (s)"
|
||||
BrightnessShortcut = "Tastenkombinationsschritte"
|
||||
|
||||
@@ -32,6 +32,7 @@ Real = "Real "
|
||||
Cartesian = "Cartesian "
|
||||
Polar = "Polar "
|
||||
Brightness = "Brightness"
|
||||
BrightnessSettings = "Brightness settings"
|
||||
SoftwareVersion = "Epsilon version"
|
||||
UpsilonVersion = "Upsilon version"
|
||||
OmegaVersion = "Omega version"
|
||||
@@ -62,7 +63,6 @@ SymbolFunction = "Expression format "
|
||||
SymbolDefaultFunction = "Default "
|
||||
SymbolArgFunction = "Empty "
|
||||
SymbolArgDefaultFunction = "Argument "
|
||||
PythonFont = "Python Font"
|
||||
MemUse = "Memory"
|
||||
DateTime = "Date/time"
|
||||
ActivateClock = "Activate clock"
|
||||
@@ -80,3 +80,7 @@ USBProtectionLevel = "Updates accepted"
|
||||
USBDefaultLevel = "Based on Upsilon"
|
||||
USBLowLevel = "Based on Omega"
|
||||
USBParanoidLevel = "None"
|
||||
Normal = "Normal"
|
||||
IdleTimeBeforeDimming = "Dim after (s)"
|
||||
IdleTimeBeforeSuspend = "Suspend after (s)"
|
||||
BrightnessShortcut = "Shortcut steps"
|
||||
|
||||
@@ -32,6 +32,7 @@ Real = "Real "
|
||||
Cartesian = "Binómica "
|
||||
Polar = "Polar "
|
||||
Brightness = "Brillo"
|
||||
BrightnessSettings = "Configuración de brillo"
|
||||
SoftwareVersion = "Versión de Epsilon"
|
||||
UpsilonVersion = "Versión de Upsilon"
|
||||
OmegaVersion = "Versión de Omega"
|
||||
@@ -62,7 +63,6 @@ SymbolFunction = "Formato expresión "
|
||||
SymbolDefaultFunction = "Defecto "
|
||||
SymbolArgFunction = "Vacío "
|
||||
SymbolArgDefaultFunction = "Argumento "
|
||||
PythonFont = "Fuente Python"
|
||||
MemUse = "Memoria"
|
||||
DateTime = "Fecha/Hora"
|
||||
ActivateClock = "Activar el reloj"
|
||||
@@ -80,3 +80,7 @@ USBProtectionLevel = "Actualizaciones aceptadas"
|
||||
USBDefaultLevel = "Basado en Upsilon"
|
||||
USBLowLevel = "Basado en Omega"
|
||||
USBParanoidLevel = "Ninguno"
|
||||
Normal = "Normal"
|
||||
IdleTimeBeforeDimming = "Oscurecer después de (s)"
|
||||
IdleTimeBeforeSuspend = "Suspender después de (s)"
|
||||
BrightnessShortcut = "Pasos de acceso directo"
|
||||
|
||||
@@ -32,6 +32,7 @@ Real = "Réel "
|
||||
Cartesian = "Algébrique "
|
||||
Polar = "Exponentielle "
|
||||
Brightness = "Luminosité"
|
||||
BrightnessSettings = "Paramètres de luminosité"
|
||||
SoftwareVersion = "Version d'Epsilon"
|
||||
UpsilonVersion = "Version d'Upsilon"
|
||||
OmegaVersion = "Version d'Omega"
|
||||
@@ -62,7 +63,6 @@ SymbolFunction = "Format expression "
|
||||
SymbolDefaultFunction = "Défaut "
|
||||
SymbolArgFunction = "Vide "
|
||||
SymbolArgDefaultFunction = "Arguments "
|
||||
PythonFont = "Police Python"
|
||||
MemUse = "Mémoire"
|
||||
DateTime = "Date/heure"
|
||||
ActivateClock = "Activer horloge"
|
||||
@@ -80,3 +80,7 @@ USBProtectionLevel = "Mise à jour acceptées"
|
||||
USBDefaultLevel = "Basées sur Upsilon"
|
||||
USBLowLevel = "Basées sur Omega"
|
||||
USBParanoidLevel = "Aucune"
|
||||
Normal = "Normale"
|
||||
IdleTimeBeforeDimming = "Assombrir après (s)"
|
||||
IdleTimeBeforeSuspend = "Éteindre après (s)"
|
||||
BrightnessShortcut = "Étapes du raccourci"
|
||||
|
||||
@@ -1,82 +1,86 @@
|
||||
SettingsApp = "Beállítások"
|
||||
SettingsAppCapital = "BEÁLLÍTÁSOK"
|
||||
AngleUnit = "Szögmérö"
|
||||
DisplayMode = "Eredmény formátuma"
|
||||
EditionMode = "Írás formátuma"
|
||||
EditionLinear = "Lineáris"
|
||||
Edition2D = "Természetes"
|
||||
ComplexFormat = "Komplex formátum"
|
||||
ExamMode = "Vizsga mód"
|
||||
ExamModeActive = "A vizsgamód újraaktiválása"
|
||||
ToDeactivateExamMode1 = "a vizsga mód kikapcsoláshoz"
|
||||
ToDeactivateExamMode2 = "csatlakoztassa a számológépet a számítógéphez"
|
||||
ToDeactivateExamMode3 = "vagy egy konnektorhoz."
|
||||
# --------------------- Please do not edit these messages ---------------------
|
||||
ExamModeWarning1 = "Vigyázat: a használt szoftver nem"
|
||||
ExamModeWarning2 = "hivatalos, Numworks nem garantálja"
|
||||
ExamModeWarning3 = "a vizsgálati mód megfelelőségét."
|
||||
AboutWarning1 = "Vigyázat: a használt szoftver"
|
||||
AboutWarning2 = "nem hivatalos. A NumWorks nem"
|
||||
AboutWarning3 = "vállal felelösséget az"
|
||||
AboutWarning4 = "esetleges károkért."
|
||||
# -----------------------------------------------------------------------------
|
||||
About = "Apropó"
|
||||
Degrees = "Fokok "
|
||||
Gradians = "Gradiens "
|
||||
Radian = "Radián "
|
||||
Decimal = "Tizedes "
|
||||
Scientific = "Tudományos "
|
||||
Engineering = "Mérnökség "
|
||||
SignificantFigures = "Tizedes számok "
|
||||
Real = "Valódi "
|
||||
Cartesian = "Kartéziánus "
|
||||
Polar = "Poláris "
|
||||
Brightness = "Fényerö"
|
||||
SoftwareVersion = "Epsilon verzió"
|
||||
UpsilonVersion = "Upsilon verzió"
|
||||
OmegaVersion = "Omega verzió"
|
||||
Username = "Felhasználónév"
|
||||
MicroPythonVersion = "µPython verzió"
|
||||
FontSizes = "Python betü méret"
|
||||
LargeFont = "Nagy "
|
||||
SmallFont = "Kicsi "
|
||||
SerialNumber = "Sorozatszám"
|
||||
UpdatePopUp = "Frissítés figyelmeztetés"
|
||||
BetaPopUp = "Béta figyelmeztetés"
|
||||
Contributors = "Közremüködök"
|
||||
Battery = "Akkumulátor"
|
||||
Accessibility = "Több vizuális beállitások"
|
||||
AccessibilityInvertColors = "Invertált színek"
|
||||
AccessibilityMagnify = "Nagyító"
|
||||
AccessibilityGamma = "Gamma korrekció"
|
||||
AccessibilityGammaRed = "Piros gamma"
|
||||
AccessibilityGammaGreen = "Zöld gamma"
|
||||
AccessibilityGammaBlue = "Kék gamma"
|
||||
MathOptions = "Matematikai beállítások"
|
||||
SymbolMultiplication = "Szorzás"
|
||||
SymbolMultiplicationCross = "Kereszt "
|
||||
SymbolMultiplicationMiddleDot = "Pont "
|
||||
SymbolMultiplicationStar = "Csillag "
|
||||
SymbolMultiplicationAutoSymbol = "Automatitus "
|
||||
SymbolFunction = "Kifejezés "
|
||||
SymbolDefaultFunction = "Alap "
|
||||
SymbolArgFunction = "Üres "
|
||||
SymbolArgDefaultFunction = "Argumentummal "
|
||||
PythonFont = "Python Betütipus"
|
||||
MemUse = "Memória"
|
||||
DateTime = "Dátum/óra"
|
||||
ActivateClock = "Óra bekapcsolása"
|
||||
Date = "Datum"
|
||||
Time = "Óra"
|
||||
RTCWarning1 = "Amikor a számológép alvómódban van, az óra"
|
||||
RTCWarning2 = "használása az elemet gyorsabban meríti ki."
|
||||
SyntaxHighlighting = "Szintaxis kiemelés"
|
||||
CursorSaving = "Kurzor mentése"
|
||||
USBExplanation1 = "Az USB-védelem megvédi"
|
||||
USBExplanation2 = "a számológépet a nem"
|
||||
USBExplanation3 = "szándékos reteszeléstől"
|
||||
USBProtection = "USB védelem"
|
||||
USBProtectionLevel = "Elfogadott frissítések"
|
||||
USBDefaultLevel = "Upsilon alapján"
|
||||
USBLowLevel = "Omega alapján"
|
||||
USBParanoidLevel = "Egyik sem"
|
||||
SettingsApp = "Beállítások"
|
||||
SettingsAppCapital = "BEÁLLÍTÁSOK"
|
||||
AngleUnit = "Szögmérö"
|
||||
DisplayMode = "Eredmény formátuma"
|
||||
EditionMode = "Írás formátuma"
|
||||
EditionLinear = "Lineáris"
|
||||
Edition2D = "Természetes"
|
||||
ComplexFormat = "Komplex formátum"
|
||||
ExamMode = "Vizsga mód"
|
||||
ExamModeActive = "A vizsgamód újraaktiválása"
|
||||
ToDeactivateExamMode1 = "a vizsga mód kikapcsoláshoz"
|
||||
ToDeactivateExamMode2 = "csatlakoztassa a számológépet a számítógéphez"
|
||||
ToDeactivateExamMode3 = "vagy egy konnektorhoz."
|
||||
# --------------------- Please do not edit these messages ---------------------
|
||||
ExamModeWarning1 = "Vigyázat: a használt szoftver nem"
|
||||
ExamModeWarning2 = "hivatalos, Numworks nem garantálja"
|
||||
ExamModeWarning3 = "a vizsgálati mód megfelelőségét."
|
||||
AboutWarning1 = "Vigyázat: a használt szoftver"
|
||||
AboutWarning2 = "nem hivatalos. A NumWorks nem"
|
||||
AboutWarning3 = "vállal felelösséget az"
|
||||
AboutWarning4 = "esetleges károkért."
|
||||
# -----------------------------------------------------------------------------
|
||||
About = "Apropó"
|
||||
Degrees = "Fokok "
|
||||
Gradians = "Gradiens "
|
||||
Radian = "Radián "
|
||||
Decimal = "Tizedes "
|
||||
Scientific = "Tudományos "
|
||||
Engineering = "Mérnökség "
|
||||
SignificantFigures = "Tizedes számok "
|
||||
Real = "Valódi "
|
||||
Cartesian = "Kartéziánus "
|
||||
Polar = "Poláris "
|
||||
Brightness = "Fényerö"
|
||||
BrightnessSettings = "Fényerő beállításai"
|
||||
SoftwareVersion = "Epsilon verzió"
|
||||
UpsilonVersion = "Upsilon verzió"
|
||||
OmegaVersion = "Omega verzió"
|
||||
Username = "Felhasználónév"
|
||||
MicroPythonVersion = "µPython verzió"
|
||||
FontSizes = "Python betü méret"
|
||||
LargeFont = "Nagy "
|
||||
SmallFont = "Kicsi "
|
||||
SerialNumber = "Sorozatszám"
|
||||
UpdatePopUp = "Frissítés figyelmeztetés"
|
||||
BetaPopUp = "Béta figyelmeztetés"
|
||||
Contributors = "Közremüködök"
|
||||
Battery = "Akkumulátor"
|
||||
Accessibility = "Több vizuális beállitások"
|
||||
AccessibilityInvertColors = "Invertált színek"
|
||||
AccessibilityMagnify = "Nagyító"
|
||||
AccessibilityGamma = "Gamma korrekció"
|
||||
AccessibilityGammaRed = "Piros gamma"
|
||||
AccessibilityGammaGreen = "Zöld gamma"
|
||||
AccessibilityGammaBlue = "Kék gamma"
|
||||
MathOptions = "Matematikai beállítások"
|
||||
SymbolMultiplication = "Szorzás"
|
||||
SymbolMultiplicationCross = "Kereszt "
|
||||
SymbolMultiplicationMiddleDot = "Pont "
|
||||
SymbolMultiplicationStar = "Csillag "
|
||||
SymbolMultiplicationAutoSymbol = "Automatitus "
|
||||
SymbolFunction = "Kifejezés "
|
||||
SymbolDefaultFunction = "Alap "
|
||||
SymbolArgFunction = "Üres "
|
||||
SymbolArgDefaultFunction = "Argumentummal "
|
||||
MemUse = "Memória"
|
||||
DateTime = "Dátum/óra"
|
||||
ActivateClock = "Óra bekapcsolása"
|
||||
Date = "Datum"
|
||||
Time = "Óra"
|
||||
RTCWarning1 = "Amikor a számológép alvómódban van, az óra"
|
||||
RTCWarning2 = "használása az elemet gyorsabban meríti ki."
|
||||
SyntaxHighlighting = "Szintaxis kiemelés"
|
||||
CursorSaving = "Kurzor mentése"
|
||||
USBExplanation1 = "Az USB-védelem megvédi"
|
||||
USBExplanation2 = "a számológépet a nem"
|
||||
USBExplanation3 = "szándékos reteszeléstől"
|
||||
USBProtection = "USB védelem"
|
||||
USBProtectionLevel = "Elfogadott frissítések"
|
||||
USBDefaultLevel = "Upsilon alapján"
|
||||
USBLowLevel = "Omega alapján"
|
||||
USBParanoidLevel = "Egyik sem"
|
||||
Normal = "Normale"
|
||||
IdleTimeBeforeDimming = "Assombrir après (s)"
|
||||
IdleTimeBeforeSuspend = "Éteindre après (s)"
|
||||
BrightnessShortcut = "Parancsikon lépések"
|
||||
|
||||
@@ -32,6 +32,7 @@ Real = "Reale "
|
||||
Cartesian = "Algebrico "
|
||||
Polar = "Esponenziale "
|
||||
Brightness = "Luminosità"
|
||||
BrightnessSettings = "Impostazioni di luminosità"
|
||||
SoftwareVersion = "Epsilon version"
|
||||
UpsilonVersion = "Upsilon version"
|
||||
OmegaVersion = "Omega version"
|
||||
@@ -62,7 +63,6 @@ SymbolFunction = "Expression format "
|
||||
SymbolDefaultFunction = "Default "
|
||||
SymbolArgFunction = "Empty "
|
||||
SymbolArgDefaultFunction = "Argument "
|
||||
PythonFont = "Python Font"
|
||||
MemUse = "Memory"
|
||||
DateTime = "Date/time"
|
||||
ActivateClock = "Activate clock"
|
||||
@@ -80,3 +80,7 @@ USBProtectionLevel = "Aggiornamenti accettati"
|
||||
USBDefaultLevel = "Basato su Upsilon"
|
||||
USBLowLevel = "A base di Omega"
|
||||
USBParanoidLevel = "Nessuno"
|
||||
Normal = "Normale"
|
||||
IdleTimeBeforeDimming = "Scurisci dopo (s)"
|
||||
IdleTimeBeforeSuspend = "Sospendi dopo (s)"
|
||||
BrightnessShortcut = "Passaggi di scelta rapida"
|
||||
|
||||
@@ -32,6 +32,7 @@ Real = "Reëel "
|
||||
Cartesian = "Cartesisch "
|
||||
Polar = "Polair "
|
||||
Brightness = "Helderheid"
|
||||
BrightnessSettings = "Helderheidsinstellingen"
|
||||
SoftwareVersion = "Epsilon version"
|
||||
UpsilonVersion = "Upsilon version"
|
||||
OmegaVersion = "Omega version"
|
||||
@@ -62,7 +63,6 @@ SymbolFunction = "Expression format "
|
||||
SymbolDefaultFunction = "Default "
|
||||
SymbolArgFunction = "Empty "
|
||||
SymbolArgDefaultFunction = "Argument "
|
||||
PythonFont = "Python Font"
|
||||
MemUse = "Memory"
|
||||
DateTime = "Date/time"
|
||||
ActivateClock = "Activate clock"
|
||||
@@ -80,3 +80,7 @@ USBProtectionLevel = "Updates geaccepteerd"
|
||||
USBDefaultLevel = "Gebaseerd op Upsilon"
|
||||
USBLowLevel = "Op basis van Omega"
|
||||
USBParanoidLevel = "Geen"
|
||||
Normal = "Normaal"
|
||||
IdleTimeBeforeDimming = "Donkerder maken na (s)"
|
||||
IdleTimeBeforeSuspend = "Suspend after (s)"
|
||||
BrightnessShortcut = "Snelkoppelingsstappen"
|
||||
|
||||
@@ -32,6 +32,7 @@ Real = "Real "
|
||||
Cartesian = "Cartesiana "
|
||||
Polar = "Polar "
|
||||
Brightness = "Brilho"
|
||||
BrightnessSettings = "Configurações de brilho"
|
||||
SoftwareVersion = "Versão do Epsilon"
|
||||
UpsilonVersion = "Versão do Upsilon"
|
||||
OmegaVersion = "Versão do Omega"
|
||||
@@ -62,7 +63,6 @@ SymbolFunction = "Formato expressão "
|
||||
SymbolDefaultFunction = "Padrão "
|
||||
SymbolArgFunction = "Vazio "
|
||||
SymbolArgDefaultFunction = "Argumento "
|
||||
PythonFont = "Fonte Python"
|
||||
MemUse = "Memória"
|
||||
DateTime = "Date/time"
|
||||
ActivateClock = "Activate clock"
|
||||
@@ -80,3 +80,7 @@ USBProtectionLevel = "Atualizações aceitas"
|
||||
USBDefaultLevel = "Baseado em Upsilon"
|
||||
USBLowLevel = "Baseado em Ômega"
|
||||
USBParanoidLevel = "Nenhum"
|
||||
Normal = "Normal"
|
||||
IdleTimeBeforeDimming = "Diminuir depois (s)"
|
||||
IdleTimeBeforeSuspend = "Suspender depois (s)"
|
||||
BrightnessShortcut = "Passos de atalho"
|
||||
|
||||
@@ -19,6 +19,7 @@ constexpr SettingsMessageTree s_usbProtectionChildren[2] = {SettingsMessageTree(
|
||||
constexpr SettingsMessageTree s_usbProtectionLevelChildren[3] = {SettingsMessageTree(I18n::Message::USBDefaultLevel), SettingsMessageTree(I18n::Message::USBLowLevel), SettingsMessageTree(I18n::Message::USBParanoidLevel)};
|
||||
constexpr SettingsMessageTree s_symbolFunctionChildren[3] = {SettingsMessageTree(I18n::Message::SymbolDefaultFunction), SettingsMessageTree(I18n::Message::SymbolArgDefaultFunction), SettingsMessageTree(I18n::Message::SymbolArgFunction)};
|
||||
constexpr SettingsMessageTree s_modelMathOptionsChildren[6] = {SettingsMessageTree(I18n::Message::AngleUnit, s_modelAngleChildren), SettingsMessageTree(I18n::Message::DisplayMode, s_modelFloatDisplayModeChildren), SettingsMessageTree(I18n::Message::EditionMode, s_modelEditionModeChildren), SettingsMessageTree(I18n::Message::SymbolFunction, s_symbolFunctionChildren), SettingsMessageTree(I18n::Message::ComplexFormat, s_modelComplexFormatChildren), SettingsMessageTree(I18n::Message::SymbolMultiplication, s_symbolChildren)};
|
||||
constexpr SettingsMessageTree s_brightnessChildren[4] = {SettingsMessageTree(I18n::Message::Brightness), SettingsMessageTree(I18n::Message::IdleTimeBeforeDimming), SettingsMessageTree(I18n::Message::IdleTimeBeforeSuspend), SettingsMessageTree(I18n::Message::BrightnessShortcut)};
|
||||
constexpr SettingsMessageTree s_accessibilityChildren[6] = {SettingsMessageTree(I18n::Message::AccessibilityInvertColors), SettingsMessageTree(I18n::Message::AccessibilityMagnify),SettingsMessageTree(I18n::Message::AccessibilityGamma),SettingsMessageTree(I18n::Message::AccessibilityGammaRed),SettingsMessageTree(I18n::Message::AccessibilityGammaGreen),SettingsMessageTree(I18n::Message::AccessibilityGammaBlue)};
|
||||
constexpr SettingsMessageTree s_contributorsChildren[18] = {SettingsMessageTree(I18n::Message::LaurianFournier), SettingsMessageTree(I18n::Message::YannCouturier), SettingsMessageTree(I18n::Message::DavidLuca), SettingsMessageTree(I18n::Message::LoicE), SettingsMessageTree(I18n::Message::VictorKretz), SettingsMessageTree(I18n::Message::QuentinGuidee), SettingsMessageTree(I18n::Message::JoachimLeFournis), SettingsMessageTree(I18n::Message::MaximeFriess), SettingsMessageTree(I18n::Message::JeanBaptisteBoric), SettingsMessageTree(I18n::Message::SandraSimmons), SettingsMessageTree(I18n::Message::David), SettingsMessageTree(I18n::Message::DamienNicolet), SettingsMessageTree(I18n::Message::EvannDreumont), SettingsMessageTree(I18n::Message::SzaboLevente), SettingsMessageTree(I18n::Message::VenceslasDuet), SettingsMessageTree(I18n::Message::CharlotteThomas), SettingsMessageTree(I18n::Message::AntoninLoubiere), SettingsMessageTree(I18n::Message::CyprienMejat)};
|
||||
|
||||
@@ -32,10 +33,10 @@ constexpr SettingsMessageTree s_modelAboutChildren[10] = {SettingsMessageTree(I1
|
||||
|
||||
MainController::MainController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate) :
|
||||
ViewController(parentResponder),
|
||||
m_brightnessCell(I18n::Message::Default, KDFont::LargeFont),
|
||||
m_popUpCell(I18n::Message::Default, KDFont::LargeFont),
|
||||
m_selectableTableView(this),
|
||||
m_mathOptionsController(this, inputEventHandlerDelegate),
|
||||
m_brightnessController(this, inputEventHandlerDelegate),
|
||||
m_localizationController(this, Metric::CommonTopMargin, LocalizationController::Mode::Language),
|
||||
m_accessibilityController(this),
|
||||
m_dateTimeController(this),
|
||||
@@ -63,13 +64,6 @@ void MainController::didBecomeFirstResponder() {
|
||||
|
||||
bool MainController::handleEvent(Ion::Events::Event event) {
|
||||
GlobalPreferences * globalPreferences = GlobalPreferences::sharedGlobalPreferences();
|
||||
if (event == Ion::Events::BrightnessPlus || event == Ion::Events::BrightnessMinus){
|
||||
int delta = Ion::Backlight::MaxBrightness/GlobalPreferences::NumberOfBrightnessStates;
|
||||
int direction = (event == Ion::Events::BrightnessPlus) ? Ion::Backlight::NumberOfStepsPerShortcut*delta : -delta*Ion::Backlight::NumberOfStepsPerShortcut;
|
||||
GlobalPreferences::sharedGlobalPreferences()->setBrightnessLevel(GlobalPreferences::sharedGlobalPreferences()->brightnessLevel()+direction);
|
||||
m_selectableTableView.reloadCellAtLocation(m_selectableTableView.selectedColumn(), 1);
|
||||
return true;
|
||||
}
|
||||
if (model()->childAtIndex(selectedRow())->numberOfChildren() == 0) {
|
||||
if (model()->childAtIndex(selectedRow())->label() == promptMessage()) {
|
||||
if (event == Ion::Events::OK || event == Ion::Events::EXE || event == Ion::Events::Right) {
|
||||
@@ -79,16 +73,6 @@ bool MainController::handleEvent(Ion::Events::Event event) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (model()->childAtIndex(selectedRow())->label() == I18n::Message::Brightness) {
|
||||
if (event == Ion::Events::Right || event == Ion::Events::Left || event == Ion::Events::Plus || event == Ion::Events::Minus) {
|
||||
int delta = Ion::Backlight::MaxBrightness/GlobalPreferences::NumberOfBrightnessStates;
|
||||
int direction = (event == Ion::Events::Right || event == Ion::Events::Plus) ? delta : -delta;
|
||||
globalPreferences->setBrightnessLevel(globalPreferences->brightnessLevel()+direction);
|
||||
m_selectableTableView.reloadCellAtLocation(m_selectableTableView.selectedColumn(), m_selectableTableView.selectedRow());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (model()->childAtIndex(selectedRow())->label() == I18n::Message::Language || model()->childAtIndex(selectedRow())->label() == I18n::Message::Country) {
|
||||
if (event == Ion::Events::OK || event == Ion::Events::EXE || event == Ion::Events::Right) {
|
||||
m_localizationController.setMode(model()->childAtIndex(selectedRow())->label() == I18n::Message::Language ? LocalizationController::Mode::Language : LocalizationController::Mode::Country);
|
||||
@@ -107,6 +91,8 @@ bool MainController::handleEvent(Ion::Events::Event event) {
|
||||
subController = &m_examModeController;
|
||||
} else if (title == I18n::Message::About) {
|
||||
subController = &m_aboutController;
|
||||
} else if (title == I18n::Message::BrightnessSettings) {
|
||||
subController = &m_brightnessController;
|
||||
} else if (title == I18n::Message::Accessibility) {
|
||||
subController = &m_accessibilityController;
|
||||
} else if (title == I18n::Message::DateTime) {
|
||||
@@ -140,11 +126,7 @@ KDCoordinate MainController::rowHeight(int j) {
|
||||
}
|
||||
|
||||
KDCoordinate MainController::cumulatedHeightFromIndex(int j) {
|
||||
KDCoordinate height = j * rowHeight(0);
|
||||
if (j > k_indexOfBrightnessCell) {
|
||||
height += CellWithSeparator::k_margin;
|
||||
}
|
||||
return height;
|
||||
return j * rowHeight(0);
|
||||
}
|
||||
|
||||
int MainController::indexFromCumulatedHeight(KDCoordinate offsetY) {
|
||||
@@ -161,11 +143,8 @@ HighlightCell * MainController::reusableCell(int index, int type) {
|
||||
return &m_cells[index];
|
||||
}
|
||||
assert(index == 0);
|
||||
if (type == 2) {
|
||||
return &m_popUpCell;
|
||||
}
|
||||
assert(type == 1);
|
||||
return &m_brightnessCell;
|
||||
assert(type == 2);
|
||||
return &m_popUpCell;
|
||||
}
|
||||
|
||||
int MainController::reusableCellCount(int type) {
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "sub_menu/math_options_controller.h"
|
||||
#include "sub_menu/preferences_controller.h"
|
||||
#include "sub_menu/usb_protection_controller.h"
|
||||
#include "sub_menu/brightness_controller.h"
|
||||
|
||||
namespace Settings {
|
||||
|
||||
@@ -31,6 +32,7 @@ extern const Shared::SettingsMessageTree s_contributorsChildren[18];
|
||||
extern const Shared::SettingsMessageTree s_modelAboutChildren[10];
|
||||
extern const Shared::SettingsMessageTree s_usbProtectionChildren[2];
|
||||
extern const Shared::SettingsMessageTree s_usbProtectionLevelChildren[3];
|
||||
extern const Shared::SettingsMessageTree s_brightnessChildren[4];
|
||||
extern const Shared::SettingsMessageTree s_model;
|
||||
|
||||
class MainController : public ViewController, public ListViewDataSource, public SelectableTableViewDataSource {
|
||||
@@ -66,12 +68,12 @@ private:
|
||||
StackViewController * stackController() const;
|
||||
I18n::Message promptMessage() const;
|
||||
bool hasPrompt() const { return promptMessage() != I18n::Message::Default; }
|
||||
constexpr static int k_numberOfSimpleChevronCells = 9;
|
||||
constexpr static int k_numberOfSimpleChevronCells = 10;
|
||||
MessageTableCellWithChevronAndMessage m_cells[k_numberOfSimpleChevronCells];
|
||||
MessageTableCellWithGaugeWithSeparator m_brightnessCell;
|
||||
MessageTableCellWithSwitch m_popUpCell;
|
||||
SelectableTableView m_selectableTableView;
|
||||
MathOptionsController m_mathOptionsController;
|
||||
BrightnessController m_brightnessController;
|
||||
LocalizationController m_localizationController;
|
||||
AccessibilityController m_accessibilityController;
|
||||
DateTimeController m_dateTimeController;
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace Settings {
|
||||
|
||||
constexpr SettingsMessageTree s_modelMenu[] =
|
||||
{SettingsMessageTree(I18n::Message::MathOptions, s_modelMathOptionsChildren),
|
||||
SettingsMessageTree(I18n::Message::Brightness),
|
||||
SettingsMessageTree(I18n::Message::BrightnessSettings, s_brightnessChildren),
|
||||
SettingsMessageTree(I18n::Message::DateTime, s_modelDateTimeChildren),
|
||||
SettingsMessageTree(I18n::Message::Language),
|
||||
SettingsMessageTree(I18n::Message::Country),
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace Settings {
|
||||
|
||||
constexpr SettingsMessageTree s_modelMenu[] =
|
||||
{SettingsMessageTree(I18n::Message::MathOptions, s_modelMathOptionsChildren),
|
||||
SettingsMessageTree(I18n::Message::Brightness),
|
||||
SettingsMessageTree(I18n::Message::BrightnessSettings, s_brightnessChildren),
|
||||
SettingsMessageTree(I18n::Message::DateTime, s_modelDateTimeChildren),
|
||||
SettingsMessageTree(I18n::Message::Language),
|
||||
SettingsMessageTree(I18n::Message::Country),
|
||||
|
||||
@@ -8,14 +8,14 @@ using namespace Shared;
|
||||
|
||||
constexpr SettingsMessageTree s_modelMenu[] =
|
||||
{SettingsMessageTree(I18n::Message::MathOptions, s_modelMathOptionsChildren),
|
||||
SettingsMessageTree(I18n::Message::Brightness),
|
||||
SettingsMessageTree(I18n::Message::BrightnessSettings, s_brightnessChildren),
|
||||
SettingsMessageTree(I18n::Message::DateTime, s_modelDateTimeChildren),
|
||||
SettingsMessageTree(I18n::Message::Language),
|
||||
SettingsMessageTree(I18n::Message::Country),
|
||||
SettingsMessageTree(I18n::Message::ExamMode, ExamModeConfiguration::s_modelExamChildren),
|
||||
#ifdef HAS_CODE
|
||||
SettingsMessageTree(I18n::Message::CodeApp, s_codeChildren),
|
||||
#endif
|
||||
#endif
|
||||
SettingsMessageTree(I18n::Message::UpdatePopUp),
|
||||
SettingsMessageTree(I18n::Message::Accessibility, s_accessibilityChildren),
|
||||
SettingsMessageTree(I18n::Message::UsbSetting, s_usbProtectionChildren),
|
||||
|
||||
142
apps/settings/sub_menu/brightness_controller.cpp
Normal file
142
apps/settings/sub_menu/brightness_controller.cpp
Normal file
@@ -0,0 +1,142 @@
|
||||
#include "brightness_controller.h"
|
||||
#include "../../global_preferences.h"
|
||||
#include "../../apps_container.h"
|
||||
#include "../../shared/poincare_helpers.h"
|
||||
#include <assert.h>
|
||||
#include <cmath>
|
||||
#include "../app.h"
|
||||
#include <apps/shared/text_field_delegate_app.h>
|
||||
#include <poincare/integer.h>
|
||||
|
||||
using namespace Poincare;
|
||||
using namespace Shared;
|
||||
|
||||
namespace Settings {
|
||||
|
||||
BrightnessController::BrightnessController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate) :
|
||||
GenericSubController(parentResponder),
|
||||
m_brightnessCell(I18n::Message::Brightness, KDFont::LargeFont),
|
||||
m_editableCellIdleBeforeDimmingSeconds(&m_selectableTableView, inputEventHandlerDelegate, this),
|
||||
m_editableCellIdleBeforeSuspendSeconds(&m_selectableTableView, inputEventHandlerDelegate, this),
|
||||
m_BrightnessShortcutCell(&m_selectableTableView, inputEventHandlerDelegate, this)
|
||||
{
|
||||
m_editableCellIdleBeforeDimmingSeconds.setMessage(I18n::Message::IdleTimeBeforeDimming);
|
||||
m_editableCellIdleBeforeDimmingSeconds.setMessageFont(KDFont::LargeFont);
|
||||
m_editableCellIdleBeforeSuspendSeconds.setMessage(I18n::Message::IdleTimeBeforeSuspend);
|
||||
m_editableCellIdleBeforeSuspendSeconds.setMessageFont(KDFont::LargeFont);
|
||||
m_BrightnessShortcutCell.setMessage(I18n::Message::BrightnessShortcut);
|
||||
m_BrightnessShortcutCell.setMessageFont(KDFont::LargeFont);
|
||||
}
|
||||
|
||||
HighlightCell * BrightnessController::reusableCell(int index, int type) {
|
||||
HighlightCell * editableCell[] = {
|
||||
&m_brightnessCell,
|
||||
&m_editableCellIdleBeforeDimmingSeconds,
|
||||
&m_editableCellIdleBeforeSuspendSeconds,
|
||||
&m_BrightnessShortcutCell
|
||||
};
|
||||
return editableCell[index];
|
||||
}
|
||||
|
||||
int BrightnessController::reusableCellCount(int type) {
|
||||
switch(type) {
|
||||
case 0:
|
||||
case 1:
|
||||
return k_totalNumberOfCell;
|
||||
default:
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void BrightnessController::willDisplayCellForIndex(HighlightCell * cell, int index) {
|
||||
if(index == 0){
|
||||
MessageTableCellWithGauge * myGaugeCell = (MessageTableCellWithGauge *)cell;
|
||||
GaugeView * myGauge = (GaugeView *)myGaugeCell->accessoryView();
|
||||
myGauge->setLevel((float)GlobalPreferences::sharedGlobalPreferences()->brightnessLevel()/(float)Ion::Backlight::MaxBrightness);
|
||||
return;
|
||||
} else {
|
||||
MessageTableCellWithEditableText * myCell = (MessageTableCellWithEditableText *)cell;
|
||||
GenericSubController::willDisplayCellForIndex(myCell, index);
|
||||
char buffer[5];
|
||||
int val;
|
||||
switch(index){
|
||||
case 1:{
|
||||
val = GlobalPreferences::sharedGlobalPreferences()->idleBeforeDimmingSeconds();
|
||||
break;
|
||||
}
|
||||
case 2:{
|
||||
val = GlobalPreferences::sharedGlobalPreferences()->idleBeforeSuspendSeconds();
|
||||
break;
|
||||
}
|
||||
case 3:{
|
||||
val = GlobalPreferences::sharedGlobalPreferences()->brightnessShortcut();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
Poincare::Integer(val).serialize(buffer, 5);
|
||||
myCell->setAccessoryText(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
bool BrightnessController::handleEvent(Ion::Events::Event event) {
|
||||
if ((selectedRow() == 0) && (event == Ion::Events::Right || event == Ion::Events::Left || event == Ion::Events::Plus || event == Ion::Events::Minus)) {
|
||||
int delta = Ion::Backlight::MaxBrightness/GlobalPreferences::NumberOfBrightnessStates;
|
||||
int direction = (event == Ion::Events::Right || event == Ion::Events::Plus) ? delta : -delta;
|
||||
GlobalPreferences::sharedGlobalPreferences()->setBrightnessLevel(GlobalPreferences::sharedGlobalPreferences()->brightnessLevel()+direction);
|
||||
m_selectableTableView.reloadCellAtLocation(m_selectableTableView.selectedColumn(), m_selectableTableView.selectedRow());
|
||||
return true;
|
||||
}
|
||||
if (event == Ion::Events::BrightnessPlus || event == Ion::Events::BrightnessMinus){
|
||||
int delta = Ion::Backlight::MaxBrightness/GlobalPreferences::NumberOfBrightnessStates;
|
||||
int NumberOfStepsPerShortcut = GlobalPreferences::sharedGlobalPreferences()->brightnessShortcut();
|
||||
int direction = (event == Ion::Events::BrightnessPlus) ? NumberOfStepsPerShortcut*delta : -delta*NumberOfStepsPerShortcut;
|
||||
GlobalPreferences::sharedGlobalPreferences()->setBrightnessLevel(GlobalPreferences::sharedGlobalPreferences()->brightnessLevel()+direction);
|
||||
m_selectableTableView.reloadCellAtLocation(m_selectableTableView.selectedColumn(), 0);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BrightnessController::textFieldShouldFinishEditing(TextField * textField, Ion::Events::Event event) {
|
||||
return ((event == Ion::Events::Up && selectedRow() > 0) || (event == Ion::Events::Down && selectedRow() < k_totalNumberOfCell - 1))
|
||||
|| TextFieldDelegate::textFieldShouldFinishEditing(textField, event);
|
||||
}
|
||||
|
||||
bool BrightnessController::textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) {
|
||||
double floatBody;
|
||||
if (textFieldDelegateApp()->hasUndefinedValue(text, floatBody)) {
|
||||
return false;
|
||||
}
|
||||
int val = std::round(floatBody);
|
||||
switch (selectedRow()) {
|
||||
case 1:
|
||||
GlobalPreferences::sharedGlobalPreferences()->setIdleBeforeDimmingSeconds(val);
|
||||
m_editableCellIdleBeforeDimmingSeconds.setAccessoryText(text);
|
||||
break;
|
||||
case 2:
|
||||
GlobalPreferences::sharedGlobalPreferences()->setIdleBeforeSuspendSeconds(val);
|
||||
m_editableCellIdleBeforeSuspendSeconds.setAccessoryText(text);
|
||||
break;
|
||||
case 3:{
|
||||
if(val > GlobalPreferences::NumberOfBrightnessStates){ val = GlobalPreferences::NumberOfBrightnessStates;
|
||||
} else if (val < 0){val = 0;}
|
||||
GlobalPreferences::sharedGlobalPreferences()->setBrightnessShortcut(val);
|
||||
m_BrightnessShortcutCell.setAccessoryText(text);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
AppsContainer * myContainer = AppsContainer::sharedAppsContainer();
|
||||
myContainer->refreshPreferences();
|
||||
m_selectableTableView.reloadCellAtLocation(0, selectedRow());
|
||||
if (event == Ion::Events::Up || event == Ion::Events::Down || event == Ion::Events::OK) {
|
||||
m_selectableTableView.handleEvent(event);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
33
apps/settings/sub_menu/brightness_controller.h
Normal file
33
apps/settings/sub_menu/brightness_controller.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef SETTINGS_BRIGHTNESS_CONTROLLER_H
|
||||
#define SETTINGS_BRIGHTNESS_CONTROLLER_H
|
||||
|
||||
#include "generic_sub_controller.h"
|
||||
#include "preferences_controller.h"
|
||||
#include "../message_table_cell_with_editable_text_with_separator.h"
|
||||
#include "../../shared/parameter_text_field_delegate.h"
|
||||
#include "../message_table_cell_with_gauge_with_separator.h"
|
||||
|
||||
namespace Settings {
|
||||
|
||||
class BrightnessController : public GenericSubController, public Shared::ParameterTextFieldDelegate {
|
||||
public:
|
||||
BrightnessController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate);
|
||||
TELEMETRY_ID("BrightnessSettings");
|
||||
HighlightCell * reusableCell(int index, int type) override;
|
||||
int reusableCellCount(int type) override;
|
||||
void willDisplayCellForIndex(HighlightCell * cell, int index) override;
|
||||
bool handleEvent(Ion::Events::Event event) override;
|
||||
bool textFieldShouldFinishEditing(TextField * textField, Ion::Events::Event event) override;
|
||||
bool textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) override;
|
||||
protected:
|
||||
constexpr static int k_totalNumberOfCell = 4;
|
||||
private:
|
||||
MessageTableCellWithGauge m_brightnessCell;
|
||||
MessageTableCellWithEditableText m_editableCellIdleBeforeDimmingSeconds;
|
||||
MessageTableCellWithEditableText m_editableCellIdleBeforeSuspendSeconds;
|
||||
MessageTableCellWithEditableText m_BrightnessShortcutCell;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,12 +1,8 @@
|
||||
ActivateDeactivate = "Aktivieren/Deaktivieren"
|
||||
ActivateDutchExamMode = "Prüfungsmodus starten NL"
|
||||
ActivateExamMode = "Prüfungsmodus starten"
|
||||
ActiveExamModeMessage1 = "Alle Ihre Daten werden "
|
||||
ActiveExamModeMessage2 = "gelöscht, wenn Sie den "
|
||||
ActiveExamModeMessage3 = "Prüfungsmodus einschalten."
|
||||
ActiveDutchExamModeMessage1 = "Alle Daten werden gelöscht, wenn"
|
||||
ActiveDutchExamModeMessage2 = "Sie den Prüfungsmodus einschalten. "
|
||||
ActiveDutchExamModeMessage3 = "Python wird nicht verfügbar sein."
|
||||
Axis = "Achse"
|
||||
Cancel = "Abbrechen"
|
||||
ClearColumn = "Spalte löschen"
|
||||
@@ -39,7 +35,6 @@ ExitExamMode2 = "Prüfungsmodus verlassen?"
|
||||
Exponential = "Exponentielle"
|
||||
FillWithFormula = "Mit einer Formel füllen"
|
||||
ForbiddenValue = "Verbotener Wert"
|
||||
FunctionColumn = "0(0) Spalte"
|
||||
FunctionOptions = "Funktionsoptionen"
|
||||
Goto = "Gehe zu"
|
||||
GraphTab = "Graph"
|
||||
@@ -59,7 +54,6 @@ Navigate = "Navigieren"
|
||||
NEnd = "N Endwert"
|
||||
Next = "Nächste"
|
||||
NoDataToPlot = "Keine Daten zum Zeichnen"
|
||||
NoFunctionToDelete = "Keine Funktion zum Löschen"
|
||||
NoValueToCompute = "Keine Größe zum Berechnen"
|
||||
NStart = "N Startwert"
|
||||
Ok = "Bestätigen"
|
||||
@@ -78,7 +72,6 @@ StandardDeviation = "Standardabweichung"
|
||||
Step = "Schrittwert"
|
||||
StorageMemoryFull1 = "Der Speicher ist voll. Löschen Sie"
|
||||
StorageMemoryFull2 = "einige Daten, dann erneut versuchen."
|
||||
StoreExpressionNotAllowed = "'store' ist verboten"
|
||||
SyntaxError = "Syntaxfehler"
|
||||
Sym = "sym"
|
||||
TEnd = "T Endwert"
|
||||
@@ -91,11 +84,15 @@ ValuesTab = "Tabelle"
|
||||
Warning = "Achtung"
|
||||
XEnd = "X Endwert"
|
||||
XStart = "X Startwert"
|
||||
Zoom = "Zoom"
|
||||
Developers = "Entwickler"
|
||||
BetaTesters = "Beta-Tester"
|
||||
ExamModeMode = "Modus"
|
||||
ExamModeModeStandard = "Standard "
|
||||
ExamModeModeNoSym = "Kein Symbol "
|
||||
ExamModeModeNoSymNoText = "Kein Symbol kein Text "
|
||||
ExamModeModeDutch = "Niederländisch "
|
||||
ColorRed = "Rot "
|
||||
ColorBlue = "Blau "
|
||||
ColorGreen = "Grün "
|
||||
ColorYellow = "Gelb "
|
||||
ColorPurple = "Violett "
|
||||
ColorPink = "Rosa "
|
||||
ColorOrange = "Orange "
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
ActivateDeactivate = "Turn on/off"
|
||||
ActivateExamMode = "Activate exam mode"
|
||||
ActivateDutchExamMode = "Activate Dutch exam mode"
|
||||
ActiveExamModeMessage1 = "All your data will be "
|
||||
ActiveExamModeMessage2 = "deleted when you activate "
|
||||
ActiveExamModeMessage3 = "the exam mode."
|
||||
ActiveDutchExamModeMessage1 = "All your data will be deleted when"
|
||||
ActiveDutchExamModeMessage2 = "you activate the exam mode. Python"
|
||||
ActiveDutchExamModeMessage3 = "application will be unavailable."
|
||||
Axis = "Axes"
|
||||
Cancel = "Cancel"
|
||||
ClearColumn = "Clear column"
|
||||
@@ -39,7 +35,6 @@ ExitExamMode2 = "mode?"
|
||||
Exponential = "Exponential"
|
||||
FillWithFormula = "Fill with a formula"
|
||||
ForbiddenValue = "Forbidden value"
|
||||
FunctionColumn = "0(0) column"
|
||||
FunctionOptions = "Function options"
|
||||
Goto = "Go to"
|
||||
GraphTab = "Graph"
|
||||
@@ -58,7 +53,6 @@ NameTooLong = "This name is too long"
|
||||
Navigate = "Navigate"
|
||||
Next = "Next"
|
||||
NoDataToPlot = "No data to draw"
|
||||
NoFunctionToDelete = "No function to delete"
|
||||
NoValueToCompute = "No values to calculate"
|
||||
NEnd = "N end"
|
||||
NStart = "N start"
|
||||
@@ -74,7 +68,6 @@ SortValues = "Sort by increasing values"
|
||||
SortSizes = "Sort by increasing frequencies"
|
||||
SquareSum = "Sum of squares"
|
||||
StandardDeviation = "Standard deviation"
|
||||
StoreExpressionNotAllowed = "'store' is not allowed"
|
||||
StatTab = "Stats"
|
||||
Step = "Step"
|
||||
StorageMemoryFull1 = "The memory is full."
|
||||
@@ -91,11 +84,15 @@ ValuesTab = "Table"
|
||||
Warning = "Warning"
|
||||
XEnd = "X end"
|
||||
XStart = "X start"
|
||||
Zoom = "Zoom"
|
||||
Developers = "Developers"
|
||||
BetaTesters = "Beta testers"
|
||||
ExamModeMode = "Mode"
|
||||
ExamModeModeStandard = "Standard "
|
||||
ExamModeModeNoSym = "No sym "
|
||||
ExamModeModeNoSymNoText = "No sym no text "
|
||||
ExamModeModeDutch = "Dutch "
|
||||
ColorRed = "Red "
|
||||
ColorBlue = "Blue "
|
||||
ColorGreen = "Green "
|
||||
ColorYellow = "Yellow "
|
||||
ColorPurple = "Purple "
|
||||
ColorPink = "Pink "
|
||||
ColorOrange = "Orange "
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
ActivateDeactivate = "Activar/Desactivar"
|
||||
ActivateExamMode = "Activar el modo examen"
|
||||
ActivateDutchExamMode = "Activar el modo examen NL"
|
||||
ActiveExamModeMessage1 = "Todos sus datos se "
|
||||
ActiveExamModeMessage2 = "eliminaran al activar "
|
||||
ActiveExamModeMessage3 = "el modo examen."
|
||||
ActiveDutchExamModeMessage1 = "Todos sus datos se eliminaran al"
|
||||
ActiveDutchExamModeMessage2 = "activar el modo examen. La aplicación"
|
||||
ActiveDutchExamModeMessage3 = "Python ya no estará disponible."
|
||||
Axis = "Ejes"
|
||||
Cancel = "Cancelar"
|
||||
ClearColumn = "Borrar la columna"
|
||||
@@ -39,7 +35,6 @@ ExitExamMode2 = "examen ?"
|
||||
Exponential = "Exponencial"
|
||||
FillWithFormula = "Rellenar con una fórmula"
|
||||
ForbiddenValue = "Valor prohibido"
|
||||
FunctionColumn = "Columna 0(0)"
|
||||
FunctionOptions = "Opciones de la función"
|
||||
Goto = "Ir a"
|
||||
GraphTab = "Gráfico"
|
||||
@@ -59,7 +54,6 @@ Navigate = "Navegar"
|
||||
NEnd = "N fin"
|
||||
Next = "Siguiente"
|
||||
NoDataToPlot = "Ningunos datos que dibujar"
|
||||
NoFunctionToDelete = "Ninguna función que eliminar"
|
||||
NoValueToCompute = "Ninguna medida que calcular"
|
||||
NStart = "N inicio"
|
||||
Ok = "Confirmar"
|
||||
@@ -78,7 +72,6 @@ StatTab = "Medidas"
|
||||
Step = "Incremento"
|
||||
StorageMemoryFull1 = "La memoria está llena."
|
||||
StorageMemoryFull2 = "Borre datos e intente de nuevo."
|
||||
StoreExpressionNotAllowed = "'store' no está permitido"
|
||||
SyntaxError = "Error sintáctico"
|
||||
Sym = "sim"
|
||||
TEnd = "T fin"
|
||||
@@ -91,11 +84,15 @@ ValuesTab = "Tabla"
|
||||
Warning = "Cuidado"
|
||||
XEnd = "X fin"
|
||||
XStart = "X inicio"
|
||||
Zoom = "Zoom"
|
||||
Developers = "Desarrolladores"
|
||||
BetaTesters = "Probadores beta"
|
||||
ExamModeMode = "Modo"
|
||||
ExamModeModeStandard = "Estándar "
|
||||
ExamModeModeNoSym = "Sin simbólico "
|
||||
ExamModeModeNoSymNoText = "Sin simbólico sin texto "
|
||||
ExamModeModeDutch = "Holandés "
|
||||
ColorRed = "Rojo "
|
||||
ColorBlue = "Azul "
|
||||
ColorGreen = "Verde "
|
||||
ColorYellow = "Amarillo "
|
||||
ColorPurple = "Púrpura "
|
||||
ColorPink = "Rosa "
|
||||
ColorOrange = "Naranja "
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
ActivateDeactivate = "Activer/Désactiver"
|
||||
ActivateExamMode = "Activer le mode examen"
|
||||
ActivateDutchExamMode = "Activer le mode examen NL"
|
||||
ActiveExamModeMessage1 = "Toutes vos données seront "
|
||||
ActiveExamModeMessage2 = "supprimées si vous activez "
|
||||
ActiveExamModeMessage3 = "le mode examen."
|
||||
ActiveDutchExamModeMessage1 = "Toutes vos données seront supprimées "
|
||||
ActiveDutchExamModeMessage2 = "si vous activez le mode examen."
|
||||
ActiveDutchExamModeMessage3 = "Python sera inaccessible."
|
||||
Axis = "Axes"
|
||||
Cancel = "Annuler"
|
||||
ClearColumn = "Effacer la colonne"
|
||||
@@ -39,7 +35,6 @@ ExitExamMode2 = "du mode examen ?"
|
||||
Exponential = "Exponentielle"
|
||||
FillWithFormula = "Remplir avec une formule"
|
||||
ForbiddenValue = "Valeur interdite"
|
||||
FunctionColumn = "Colonne 0(0)"
|
||||
FunctionOptions = "Options de la fonction"
|
||||
Goto = "Aller à"
|
||||
GraphTab = "Graphique"
|
||||
@@ -59,7 +54,6 @@ Navigate = "Naviguer"
|
||||
Next = "Suivant"
|
||||
NEnd = "N fin"
|
||||
NoDataToPlot = "Aucune donnée à tracer"
|
||||
NoFunctionToDelete = "Pas de fonction à supprimer"
|
||||
NoValueToCompute = "Aucune grandeur à calculer"
|
||||
NStart = "N début"
|
||||
Ok = "Valider"
|
||||
@@ -78,7 +72,6 @@ StatTab = "Stats"
|
||||
Step = "Pas"
|
||||
StorageMemoryFull1 = "La mémoire est pleine."
|
||||
StorageMemoryFull2 = "Effacez des données et réessayez."
|
||||
StoreExpressionNotAllowed = "'store' n'est pas autorisé"
|
||||
SyntaxError = "Attention à la syntaxe"
|
||||
Sym = "sym"
|
||||
TEnd = "T fin"
|
||||
@@ -91,11 +84,15 @@ ValuesTab = "Tableau"
|
||||
Warning = "Attention"
|
||||
XEnd = "X fin"
|
||||
XStart = "X début"
|
||||
Zoom = "Zoom"
|
||||
Developers = "Développeurs"
|
||||
BetaTesters = "Beta testeurs"
|
||||
ExamModeMode = "Mode"
|
||||
ExamModeModeStandard = "Standard "
|
||||
ExamModeModeNoSym = "Sans symbolique "
|
||||
ExamModeModeNoSymNoText = "Sans symbolique ni texte "
|
||||
ExamModeModeDutch = "Dutch "
|
||||
ColorRed = "Rouge "
|
||||
ColorBlue = "Bleu "
|
||||
ColorGreen = "Vert "
|
||||
ColorYellow = "Jaune "
|
||||
ColorPurple = "Violet "
|
||||
ColorPink = "Rose "
|
||||
ColorOrange = "Orange "
|
||||
|
||||
@@ -1,101 +1,98 @@
|
||||
ActivateDeactivate = "Ki/Be kapcsolás"
|
||||
ActivateExamMode = "A vizsgálati mód aktiválása"
|
||||
ActivateDutchExamMode = "A holland vizsga mód aktiválása"
|
||||
ActiveExamModeMessage1 = "Az összes adatod"
|
||||
ActiveExamModeMessage2 = "törölve lesz ha"
|
||||
ActiveExamModeMessage3 = "a vizsga módot aktiválja."
|
||||
ActiveDutchExamModeMessage1 = "Az összes adatod törölve lesz"
|
||||
ActiveDutchExamModeMessage2 = "ha a vizsga módot aktiválja. A"
|
||||
ActiveDutchExamModeMessage3 = "Python alkalmazás használhatatlan lesz."
|
||||
Axis = "Tengelyek"
|
||||
Cancel = "Mégse"
|
||||
ClearColumn = "Oszlop törlése"
|
||||
ColumnOptions = "Oszlop opciók"
|
||||
ConfirmDiscard1 = "Minden változtatást elvetünk"
|
||||
ConfirmDiscard2 = ""
|
||||
CopyColumnInList = "Az oszlopot egy listába másolni"
|
||||
Country = "Ország"
|
||||
CountryCA = "Kanada "
|
||||
CountryDE = "Németország "
|
||||
CountryES = "Spanyolország "
|
||||
CountryFR = "Franciaország "
|
||||
CountryGB = "Egyesült Királyság "
|
||||
CountryIT = "Olaszország "
|
||||
CountryNL = "Hollandia "
|
||||
CountryPT = "Portugália "
|
||||
CountryUS = "Egyesült Államok "
|
||||
CountryWW = "Nemzetközi "
|
||||
CountryWarning1 = "Ez a beállítás meghatározza az"
|
||||
CountryWarning2 = "alkalmazott tematikus konvenciókat."
|
||||
DataNotSuitable = "Az adatok nem felelnek meg"
|
||||
DataTab = "Adatok"
|
||||
Deg = "deg"
|
||||
Deviation = "Varianca"
|
||||
DisplayValues = "Értékek mutatása"
|
||||
Empty = "Üres"
|
||||
Eng = "eng"
|
||||
ExitExamMode1 = "Kilépni a vizsga "
|
||||
ExitExamMode2 = "módból?"
|
||||
Exponential = "Exponenciális"
|
||||
FillWithFormula = "Töltse ki egy képlettel"
|
||||
ForbiddenValue = "Tiltott érték"
|
||||
FunctionColumn = "0(0) oszlop"
|
||||
FunctionOptions = "Funkció opciók"
|
||||
Goto = "Menj ..."
|
||||
GraphTab = "Grafikon"
|
||||
HardwareTestLaunch1 = "A hardverteszt indítása :"
|
||||
HardwareTestLaunch2 = "Nyomjon a reset gombra a"
|
||||
HardwareTestLaunch3 = "teszt megállításához (ez"
|
||||
HardwareTestLaunch4 = "az adatokat törölni fogja)"
|
||||
IntervalSet = "Állítsa be az intervallumot"
|
||||
Language = "Nyelv"
|
||||
LowBattery = "Majdnem kimerült az elem"
|
||||
Mean = "középérték"
|
||||
Move = " Odébb rakni: "
|
||||
NameCannotStartWithNumber = "Egy név nem kezdöthet számmal"
|
||||
NameTaken = "Ez a név foglalt"
|
||||
NameTooLong = "Ez a név túl hosszú"
|
||||
Navigate = "Hajózik"
|
||||
Next = "következö"
|
||||
NEnd = "N vége"
|
||||
NoDataToPlot = "Nincs rajzolható adat"
|
||||
NoFunctionToDelete = "Nincs törölhetö függvény"
|
||||
NoValueToCompute = "Nincs számítható érték"
|
||||
NStart = "N kezdete"
|
||||
Ok = "Érvényesítés"
|
||||
Or = " vagy "
|
||||
Orthonormal = "Ortonormált"
|
||||
Plot = "Grafikon rajzolása"
|
||||
PoolMemoryFull1 = "A memória megtelt."
|
||||
PoolMemoryFull2 = "Kérem próbálja újra."
|
||||
Rename = "Átnevezés"
|
||||
Sci = "sci"
|
||||
SortValues = "Rendezés értékek növelésével"
|
||||
SortSizes = "Rendezés növekvő frekvenciák szerint"
|
||||
SquareSum = "Négyzetek összege"
|
||||
StandardDeviation = "Alap eltérés"
|
||||
StatTab = "Statisztikák"
|
||||
Step = "Lépés"
|
||||
StorageMemoryFull1 = "A memória megtelt."
|
||||
StorageMemoryFull2 = "Törlöljön adatokat és próbálkozzon újra."
|
||||
StoreExpressionNotAllowed = "'szore' nem engedélyezett"
|
||||
SyntaxError = "Szintaxis hiba"
|
||||
Sym = "sym"
|
||||
TEnd = "T vég"
|
||||
ThetaEnd = "θ vége"
|
||||
ThetaStart = "θ kezdete"
|
||||
TStart = "T kezdete"
|
||||
ToZoom = "Nagyítani : "
|
||||
UndefinedValue = "Meghatározatlan adat"
|
||||
ValuesTab = "Táblázat"
|
||||
Warning = "Figyelem"
|
||||
XEnd = "X vége"
|
||||
XStart = "X kezdete"
|
||||
Zoom = "Nagyítás"
|
||||
Developers = "Kifejlesztök"
|
||||
BetaTesters = "Béta tesztelök"
|
||||
ExamModeMode = "Üzemmód"
|
||||
ExamModeModeStandard = "Normál "
|
||||
ExamModeModeNoSym = "Szimbólikus nélkül "
|
||||
ExamModeModeNoSymNoText = "Szimbólikus és szöveg nélkül "
|
||||
ExamModeModeDutch = "Holland "
|
||||
ActivateDeactivate = "Ki/Be kapcsolás"
|
||||
ActivateExamMode = "A vizsgálati mód aktiválása"
|
||||
ActiveExamModeMessage1 = "Az összes adatod"
|
||||
ActiveExamModeMessage2 = "törölve lesz ha"
|
||||
ActiveExamModeMessage3 = "a vizsga módot aktiválja."
|
||||
Axis = "Tengelyek"
|
||||
Cancel = "Mégse"
|
||||
ClearColumn = "Oszlop törlése"
|
||||
ColumnOptions = "Oszlop opciók"
|
||||
ConfirmDiscard1 = "Minden változtatást elvetünk"
|
||||
ConfirmDiscard2 = ""
|
||||
CopyColumnInList = "Az oszlopot egy listába másolni"
|
||||
Country = "Ország"
|
||||
CountryCA = "Kanada "
|
||||
CountryDE = "Németország "
|
||||
CountryES = "Spanyolország "
|
||||
CountryFR = "Franciaország "
|
||||
CountryGB = "Egyesült Királyság "
|
||||
CountryIT = "Olaszország "
|
||||
CountryNL = "Hollandia "
|
||||
CountryPT = "Portugália "
|
||||
CountryUS = "Egyesült Államok "
|
||||
CountryWW = "Nemzetközi "
|
||||
CountryWarning1 = "Ez a beállítás meghatározza az"
|
||||
CountryWarning2 = "alkalmazott tematikus konvenciókat."
|
||||
DataNotSuitable = "Az adatok nem felelnek meg"
|
||||
DataTab = "Adatok"
|
||||
Deg = "deg"
|
||||
Deviation = "Varianca"
|
||||
DisplayValues = "Értékek mutatása"
|
||||
Empty = "Üres"
|
||||
Eng = "eng"
|
||||
ExitExamMode1 = "Kilépni a vizsga "
|
||||
ExitExamMode2 = "módból?"
|
||||
Exponential = "Exponenciális"
|
||||
FillWithFormula = "Töltse ki egy képlettel"
|
||||
ForbiddenValue = "Tiltott érték"
|
||||
FunctionOptions = "Funkció opciók"
|
||||
Goto = "Menj ..."
|
||||
GraphTab = "Grafikon"
|
||||
HardwareTestLaunch1 = "A hardverteszt indítása :"
|
||||
HardwareTestLaunch2 = "Nyomjon a reset gombra a"
|
||||
HardwareTestLaunch3 = "teszt megállításához (ez"
|
||||
HardwareTestLaunch4 = "az adatokat törölni fogja)"
|
||||
IntervalSet = "Állítsa be az intervallumot"
|
||||
Language = "Nyelv"
|
||||
LowBattery = "Majdnem kimerült az elem"
|
||||
Mean = "középérték"
|
||||
Move = " Odébb rakni: "
|
||||
NameCannotStartWithNumber = "Egy név nem kezdöthet számmal"
|
||||
NameTaken = "Ez a név foglalt"
|
||||
NameTooLong = "Ez a név túl hosszú"
|
||||
Navigate = "Hajózik"
|
||||
Next = "következö"
|
||||
NEnd = "N vége"
|
||||
NoDataToPlot = "Nincs rajzolható adat"
|
||||
NoValueToCompute = "Nincs számítható érték"
|
||||
NStart = "N kezdete"
|
||||
Ok = "Érvényesítés"
|
||||
Or = " vagy "
|
||||
Orthonormal = "Ortonormált"
|
||||
Plot = "Grafikon rajzolása"
|
||||
PoolMemoryFull1 = "A memória megtelt."
|
||||
PoolMemoryFull2 = "Kérem próbálja újra."
|
||||
Rename = "Átnevezés"
|
||||
Sci = "sci"
|
||||
SortValues = "Rendezés értékek növelésével"
|
||||
SortSizes = "Rendezés növekvő frekvenciák szerint"
|
||||
SquareSum = "Négyzetek összege"
|
||||
StandardDeviation = "Alap eltérés"
|
||||
StatTab = "Statisztikák"
|
||||
Step = "Lépés"
|
||||
StorageMemoryFull1 = "A memória megtelt."
|
||||
StorageMemoryFull2 = "Törlöljön adatokat és próbálkozzon újra."
|
||||
SyntaxError = "Szintaxis hiba"
|
||||
Sym = "sym"
|
||||
TEnd = "T vég"
|
||||
ThetaEnd = "θ vége"
|
||||
ThetaStart = "θ kezdete"
|
||||
TStart = "T kezdete"
|
||||
ToZoom = "Nagyítani : "
|
||||
UndefinedValue = "Meghatározatlan adat"
|
||||
ValuesTab = "Táblázat"
|
||||
Warning = "Figyelem"
|
||||
XEnd = "X vége"
|
||||
XStart = "X kezdete"
|
||||
ExamModeMode = "Üzemmód"
|
||||
ExamModeModeStandard = "Normál "
|
||||
ExamModeModeNoSym = "Szimbólikus nélkül "
|
||||
ExamModeModeNoSymNoText = "Szimbólikus és szöveg nélkül "
|
||||
ExamModeModeDutch = "Holland "
|
||||
ColorRed = "Piros "
|
||||
ColorBlue = "Kék "
|
||||
ColorGreen = "Zöld "
|
||||
ColorYellow = "Sárga "
|
||||
ColorPurple = "Lila "
|
||||
ColorPink = "Rózsaszín "
|
||||
ColorOrange = "Narancssárga "
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
ActivateDeactivate = "Attivare/Disattivare"
|
||||
ActivateExamMode = "Attiva modalità d'esame"
|
||||
ActivateDutchExamMode = "Attiva modalità d'esame NL"
|
||||
ActiveExamModeMessage1 = "Tutti i tuoi dati saranno "
|
||||
ActiveExamModeMessage2 = "cancellati se attivi "
|
||||
ActiveExamModeMessage3 = "la modalità d'esame."
|
||||
ActiveDutchExamModeMessage1 = "Tutti i tuoi dati saranno cancellati"
|
||||
ActiveDutchExamModeMessage2 = "se attivi la modalità d'esame."
|
||||
ActiveDutchExamModeMessage3 = "L'app Python sarà inaccessibile."
|
||||
Axis = "Assi"
|
||||
Cancel = "Annullare"
|
||||
ClearColumn = "Cancella la colonna"
|
||||
@@ -39,7 +35,6 @@ ExitExamMode2 = "dalla modalità d'esame ?"
|
||||
Exponential = "Esponenziale"
|
||||
FillWithFormula = "Compilare con una formula"
|
||||
ForbiddenValue = "Valore non consentito"
|
||||
FunctionColumn = "Colonna 0(0)"
|
||||
FunctionOptions = "Opzioni della funzione"
|
||||
Goto = "Andare a"
|
||||
GraphTab = "Grafico"
|
||||
@@ -59,7 +54,6 @@ Navigate = "Navigare"
|
||||
Next = "Successivo"
|
||||
NEnd = "N finale"
|
||||
NoDataToPlot = "Nessun dato da tracciare"
|
||||
NoFunctionToDelete = "Nessuna funzione da cancellare"
|
||||
NoValueToCompute = "Nessun valore da calcolare"
|
||||
NStart = "N iniziale"
|
||||
Ok = "Conferma"
|
||||
@@ -78,7 +72,6 @@ StatTab = "Stats"
|
||||
Step = "Passo"
|
||||
StorageMemoryFull1 = "La memoria è piena."
|
||||
StorageMemoryFull2 = "Cancellate i dati e riprovate."
|
||||
StoreExpressionNotAllowed = "'store' non è consentito"
|
||||
SyntaxError = "Sintassi errata"
|
||||
Sym = "sym"
|
||||
TEnd = "T finale"
|
||||
@@ -91,11 +84,15 @@ ValuesTab = "Tabella"
|
||||
Warning = "Attenzione"
|
||||
XEnd = "X finale"
|
||||
XStart = "X iniziale"
|
||||
Zoom = "Zoom"
|
||||
Developers = "Developers"
|
||||
BetaTesters = "Beta testers"
|
||||
ExamModeMode = "Modalità"
|
||||
ExamModeModeStandard = "Standard "
|
||||
ExamModeModeNoSym = "Nessun simbolo "
|
||||
ExamModeModeNoSymNoText = "Nessun simbolo nessun testo "
|
||||
ExamModeModeDutch = "Olandese "
|
||||
ColorRed = "Rosso "
|
||||
ColorBlue = "Blu "
|
||||
ColorGreen = "Verde "
|
||||
ColorYellow = "Giallo "
|
||||
ColorPurple = "Viola "
|
||||
ColorPink = "Rosa "
|
||||
ColorOrange = "Arancia "
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
ActivateDeactivate = "Zet aan/uit"
|
||||
ActivateExamMode = "Internationale examenst."
|
||||
ActivateDutchExamMode = "Nederlandse examenstand"
|
||||
ActiveExamModeMessage1 = "Al je gegevens worden "
|
||||
ActiveExamModeMessage2 = "gewist wanneer je de "
|
||||
ActiveExamModeMessage3 = "examenstand activeert."
|
||||
ActiveDutchExamModeMessage1 = "Al je gegevens worden gewist wanneer"
|
||||
ActiveDutchExamModeMessage2 = "je de examenstand activeert. De Python"
|
||||
ActiveDutchExamModeMessage3 = "applicatie wordt uitgeschakeld."
|
||||
Axis = "Assen"
|
||||
Cancel = "Annuleer"
|
||||
ClearColumn = "Wis kolom"
|
||||
@@ -39,7 +35,6 @@ ExitExamMode2 = "examenstand?"
|
||||
Exponential = "Exponentieel"
|
||||
FillWithFormula = "Vul met een formule"
|
||||
ForbiddenValue = "Verboden waarde"
|
||||
FunctionColumn = "0(0) kolom"
|
||||
FunctionOptions = "Functie-opties"
|
||||
Goto = "Ga naar"
|
||||
GraphTab = "Grafiek"
|
||||
@@ -58,7 +53,6 @@ NameTooLong = "Deze naam is te lang"
|
||||
Navigate = "Navigeren"
|
||||
Next = "Volgende"
|
||||
NoDataToPlot = "Geen gegevens om te plotten"
|
||||
NoFunctionToDelete = "Geen functie om te verwijderen"
|
||||
NoValueToCompute = "Geen waarden om te berekenen"
|
||||
NEnd = "N einde"
|
||||
NStart = "N begin"
|
||||
@@ -74,7 +68,6 @@ SortValues = "Sorteer waarden oplopend"
|
||||
SortSizes = "Sorteer frequenties oplopend"
|
||||
SquareSum = "Som van kwadraten"
|
||||
StandardDeviation = "Standaardafwijking"
|
||||
StoreExpressionNotAllowed = "'opslaan' is niet toegestaan"
|
||||
StatTab = "Stats"
|
||||
Step = "Stap"
|
||||
StorageMemoryFull1 = "Het geheugen is vol."
|
||||
@@ -91,11 +84,15 @@ ValuesTab = "Tabel"
|
||||
Warning = "Waarschuwing"
|
||||
XEnd = "X einde"
|
||||
XStart = "X begin"
|
||||
Zoom = "Zoom"
|
||||
Developers = "Developers"
|
||||
BetaTesters = "Beta testers"
|
||||
ExamModeMode = "Mode"
|
||||
ExamModeModeStandard = "Standaard "
|
||||
ExamModeModeNoSym = "Geen sym "
|
||||
ExamModeModeNoSymNoText = "Geen sym geen tekst "
|
||||
ExamModeModeDutch = "Nederlands "
|
||||
ColorRed = "rood"
|
||||
ColorBlue = "Blauw"
|
||||
ColorGreen = "Groente"
|
||||
ColorYellow = "Geel"
|
||||
ColorPurple = "Purper"
|
||||
ColorPink = "Roze"
|
||||
ColorOrange = "Oranje"
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
ActivateDeactivate = "Ativar/Desativar"
|
||||
ActivateExamMode = "Ativar o modo de exame"
|
||||
ActivateDutchExamMode = "Ativar o modo de exame NL"
|
||||
ActiveExamModeMessage1 = "Todos os seus dados serão "
|
||||
ActiveExamModeMessage2 = "apagados se ativar "
|
||||
ActiveExamModeMessage3 = "o modo de exame."
|
||||
ActiveDutchExamModeMessage1 = "Todos os seus dados serão apagados "
|
||||
ActiveDutchExamModeMessage2 = "se ativar o modo de exame. A"
|
||||
ActiveDutchExamModeMessage3 = "aplicação Python estará indisponível."
|
||||
Axis = "Eixos"
|
||||
Cancel = "Cancelar"
|
||||
ClearColumn = "Excluir coluna"
|
||||
@@ -39,7 +35,6 @@ ExitExamMode2 = "exame ?"
|
||||
Exponential = "Exponencial"
|
||||
FillWithFormula = "Preencher com uma fórmula"
|
||||
ForbiddenValue = "Valor proibido"
|
||||
FunctionColumn = "Coluna 0(0)"
|
||||
FunctionOptions = "Opções de função"
|
||||
Goto = "Ir para"
|
||||
GraphTab = "Gráfico"
|
||||
@@ -59,7 +54,6 @@ Navigate = "Navegar"
|
||||
NEnd = "N fim"
|
||||
Next = "Seguinte"
|
||||
NoDataToPlot = "Não há dados para desenhar"
|
||||
NoFunctionToDelete = "Sem função para eliminar"
|
||||
NoValueToCompute = "Não há dados para calcular"
|
||||
NStart = "N início"
|
||||
Ok = "Confirmar"
|
||||
@@ -78,7 +72,6 @@ StatTab = "Estat"
|
||||
Step = "Passo"
|
||||
StorageMemoryFull1 = "A memória esta cheia."
|
||||
StorageMemoryFull2 = "Apage dados e tente novamente."
|
||||
StoreExpressionNotAllowed = "'store' não está permitido"
|
||||
SyntaxError = "Erro de sintaxe"
|
||||
Sym = "sim"
|
||||
TEnd = "T fim"
|
||||
@@ -91,11 +84,15 @@ ValuesTab = "Tabela"
|
||||
Warning = "Atenção"
|
||||
XEnd = "X fim"
|
||||
XStart = "X início"
|
||||
Zoom = "Zoom"
|
||||
Developers = "Desenvolvedores"
|
||||
BetaTesters = "Testadores beta"
|
||||
ExamModeMode = "Modo"
|
||||
ExamModeModeStandard = "Padrão "
|
||||
ExamModeModeNoSym = "Sem sym "
|
||||
ExamModeModeNoSymNoText = "Sem sym sem texto "
|
||||
ExamModeModeDutch = "holandês "
|
||||
ColorRed = "Vermelho "
|
||||
ColorBlue = "Azul "
|
||||
ColorGreen = "Verde "
|
||||
ColorYellow = "Amarelo "
|
||||
ColorPurple = "Roxa "
|
||||
ColorPink = "Cor de rosa "
|
||||
ColorOrange = "Laranja "
|
||||
|
||||
@@ -25,7 +25,6 @@ UnitMassGramKiloSymbol = "_kg"
|
||||
UnitMassGramSymbol = "_g"
|
||||
UnitMassGramMilliSymbol = "_mg"
|
||||
UnitMassGramMicroSymbol = "_μg"
|
||||
UnitMassGramNanoSymbol = "_ng"
|
||||
UnitMassTonneSymbol = "_t"
|
||||
UnitMassOunceSymbol = "_oz"
|
||||
UnitMassPoundSymbol = "_lb"
|
||||
@@ -122,7 +121,6 @@ DeterminantCommandWithArg = "det(M)"
|
||||
DiffCommandWithArg = "diff(f(x),x,a)"
|
||||
DiffCommand = "diff(\x11,x,\x11)"
|
||||
DimensionCommandWithArg = "dim(M)"
|
||||
DiscriminantFormulaDegree2 = "Δ=b^2-4ac"
|
||||
DotCommandWithArg = "dot(u,v)"
|
||||
E = "e"
|
||||
Equal = "="
|
||||
@@ -352,7 +350,6 @@ PVenceslasDuet = "@Citorva"
|
||||
CyprienMejat = "Cyprien Méjat"
|
||||
PCyprienMejat = "@A2drien"
|
||||
SpeedOfLight = "2.99792458·10^8_m_s^-1"
|
||||
YearLight = "9.461·10^15_m"
|
||||
Boltzmann = "1.380649·10^-23_J_K^-1"
|
||||
StefanBoltzmann = "5.670374419·10^-8_W_m^-2_K^-4"
|
||||
VacuumImpedance = "376.730313668_Ω"
|
||||
|
||||
@@ -29,6 +29,8 @@ app_shared_src = $(addprefix apps/shared/,\
|
||||
buffer_function_title_cell.cpp \
|
||||
buffer_text_view_with_text_field.cpp \
|
||||
button_with_separator.cpp \
|
||||
color_cell.cpp \
|
||||
color_parameter_controller.cpp \
|
||||
cursor_view.cpp \
|
||||
editable_cell_table_view_controller.cpp \
|
||||
expression_field_delegate_app.cpp \
|
||||
|
||||
51
apps/shared/color_cell.cpp
Normal file
51
apps/shared/color_cell.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
#include "color_cell.h"
|
||||
|
||||
namespace Shared {
|
||||
|
||||
constexpr const I18n::Message MessageTableCellWithColor::k_textForIndex[Palette::numberOfDataColors()];
|
||||
|
||||
constexpr const uint8_t colorMask[MessageTableCellWithColor::ColorView::k_colorSize][MessageTableCellWithColor::ColorView::k_colorSize] = { // FIXME Can't link with constexpr static
|
||||
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
|
||||
{0xFF, 0xFF, 0xFF, 0xE1, 0x0C, 0x00, 0x00, 0x0C, 0xE1, 0xFF, 0xFF, 0xFF},
|
||||
{0xFF, 0xFF, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0xFF, 0xFF},
|
||||
{0xFF, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE1, 0xFF},
|
||||
{0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xFF},
|
||||
{0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF},
|
||||
{0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF},
|
||||
{0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xFF},
|
||||
{0xFF, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE1, 0xFF},
|
||||
{0xFF, 0xFF, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0xFF, 0xFF},
|
||||
{0xFF, 0xFF, 0xFF, 0xE1, 0x0C, 0x00, 0x00, 0x0C, 0xE1, 0xFF, 0xFF, 0xFF},
|
||||
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
|
||||
};
|
||||
|
||||
MessageTableCellWithColor::MessageTableCellWithColor() :
|
||||
MessageTableCell(),
|
||||
m_accessoryView()
|
||||
{}
|
||||
|
||||
View * MessageTableCellWithColor::accessoryView() const {
|
||||
return (View *)&m_accessoryView;
|
||||
}
|
||||
|
||||
void MessageTableCellWithColor::setColor(int i) {
|
||||
m_accessoryView.setColor(i);
|
||||
MessageTextView * label = (MessageTextView*)(labelView());
|
||||
return label->setMessage(k_textForIndex[i]);
|
||||
}
|
||||
|
||||
MessageTableCellWithColor::ColorView::ColorView() :
|
||||
m_index(0)
|
||||
{}
|
||||
|
||||
void MessageTableCellWithColor::ColorView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
KDColor Buffer[MessageTableCellWithColor::ColorView::k_colorSize*MessageTableCellWithColor::ColorView::k_colorSize];
|
||||
KDRect Frame(bounds().x(), bounds().y() + bounds().height()/2 - k_colorSize/2, k_colorSize, k_colorSize);
|
||||
ctx->blendRectWithMask(Frame, Palette::DataColor[m_index], (const uint8_t *)colorMask, Buffer);
|
||||
}
|
||||
|
||||
KDSize MessageTableCellWithColor::ColorView::minimalSizeForOptimalDisplay() const {
|
||||
return KDSize(k_colorSize, k_colorSize);
|
||||
}
|
||||
|
||||
}
|
||||
42
apps/shared/color_cell.h
Normal file
42
apps/shared/color_cell.h
Normal file
@@ -0,0 +1,42 @@
|
||||
#ifndef SHARED_COLOR_CELL_CONTROLLER_H
|
||||
#define SHARED_COLOR_CELL_CONTROLLER_H
|
||||
|
||||
#include <escher.h>
|
||||
#include <apps/i18n.h>
|
||||
|
||||
namespace Shared {
|
||||
|
||||
class MessageTableCellWithColor : public MessageTableCell {
|
||||
public:
|
||||
MessageTableCellWithColor();
|
||||
View * accessoryView() const override;
|
||||
void setColor(int i);
|
||||
int color() { return m_accessoryView.color(); }
|
||||
constexpr static I18n::Message k_textForIndex[Palette::numberOfDataColors()] = {
|
||||
I18n::Message::ColorRed,
|
||||
I18n::Message::ColorBlue,
|
||||
I18n::Message::ColorGreen,
|
||||
I18n::Message::ColorYellow,
|
||||
I18n::Message::ColorPurple,
|
||||
I18n::Message::ColorBlue,
|
||||
I18n::Message::ColorPink,
|
||||
I18n::Message::ColorOrange
|
||||
};
|
||||
class ColorView : public TransparentView {
|
||||
public:
|
||||
ColorView();
|
||||
void setColor(int i) { m_index = i; }
|
||||
int color() { return m_index; }
|
||||
void drawRect(KDContext * ctx, KDRect rect) const override;
|
||||
KDSize minimalSizeForOptimalDisplay() const override;
|
||||
constexpr static KDCoordinate k_colorSize = 12;
|
||||
private:
|
||||
int m_index;
|
||||
};
|
||||
private:
|
||||
ColorView m_accessoryView;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
86
apps/shared/color_parameter_controller.cpp
Normal file
86
apps/shared/color_parameter_controller.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
#include "color_parameter_controller.h"
|
||||
|
||||
#include "function_app.h"
|
||||
#include "../apps_container.h"
|
||||
#include <assert.h>
|
||||
|
||||
namespace Shared {
|
||||
|
||||
ColorParameterController::ColorParameterController(Responder * parentResponder, I18n::Message title) :
|
||||
ViewController(parentResponder),
|
||||
m_selectableTableView(this),
|
||||
m_record(),
|
||||
m_title(title)
|
||||
{}
|
||||
|
||||
void ColorParameterController::viewWillAppear() {
|
||||
ViewController::viewWillAppear();
|
||||
// Restore the selected color
|
||||
KDColor FunctionColor = function()->color();
|
||||
uint8_t cellXPosition = 0;
|
||||
// TODO: Improve this if possible
|
||||
for (uint8_t i = 0; i < sizeof(Palette::DataColor)/sizeof(Palette::DataColor[0]); i++) {
|
||||
if (Palette::DataColor[i] == FunctionColor) {
|
||||
cellXPosition = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(Palette::DataColor[cellXPosition] == FunctionColor);
|
||||
selectCellAtLocation(0, cellXPosition);
|
||||
m_selectableTableView.reloadData();
|
||||
}
|
||||
|
||||
void ColorParameterController::didBecomeFirstResponder() {
|
||||
Container::activeApp()->setFirstResponder(&m_selectableTableView);
|
||||
}
|
||||
|
||||
bool ColorParameterController::handleEvent(Ion::Events::Event event) {
|
||||
StackViewController * stack = (StackViewController *)(parentResponder());
|
||||
if (event == Ion::Events::Left) {
|
||||
stack->pop();
|
||||
return true;
|
||||
}
|
||||
if (event == Ion::Events::OK || event == Ion::Events::EXE) {
|
||||
handleEnterOnRow(selectedRow());
|
||||
stack->pop();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
KDCoordinate ColorParameterController::cellHeight() {
|
||||
return Metric::ParameterCellHeight;
|
||||
}
|
||||
|
||||
HighlightCell * ColorParameterController::reusableCell(int index) {
|
||||
assert(index < numberOfRows());
|
||||
return &m_cells[index];
|
||||
}
|
||||
|
||||
void ColorParameterController::willDisplayCellForIndex(HighlightCell * cell, int index) {
|
||||
MessageTableCellWithColor * myCell = (MessageTableCellWithColor *)cell;
|
||||
myCell->setColor(index);
|
||||
myCell->setMessageFont(KDFont::LargeFont);
|
||||
cell->reloadCell();
|
||||
}
|
||||
|
||||
bool ColorParameterController::handleEnterOnRow(int rowIndex) {
|
||||
function()->setColor(Palette::DataColor[rowIndex]);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ColorParameterController::setRecord(Ion::Storage::Record record) {
|
||||
m_record = record;
|
||||
selectCellAtLocation(0, 0);
|
||||
}
|
||||
|
||||
ExpiringPointer<Function> ColorParameterController::function() {
|
||||
return functionStore()->modelForRecord(m_record);
|
||||
}
|
||||
|
||||
FunctionStore * ColorParameterController::functionStore() {
|
||||
return FunctionApp::app()->functionStore();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
44
apps/shared/color_parameter_controller.h
Normal file
44
apps/shared/color_parameter_controller.h
Normal file
@@ -0,0 +1,44 @@
|
||||
#ifndef SHARED_COLOR_PARAM_CONTROLLER_H
|
||||
#define SHARED_COLOR_PARAM_CONTROLLER_H
|
||||
|
||||
#include <escher.h>
|
||||
#include "function_store.h"
|
||||
#include "color_cell.h"
|
||||
#include <apps/i18n.h>
|
||||
|
||||
namespace Shared {
|
||||
|
||||
class ColorParameterController : public ViewController, public SimpleListViewDataSource, public SelectableTableViewDataSource {
|
||||
public:
|
||||
ColorParameterController(Responder * parentResponder, I18n::Message title);
|
||||
|
||||
View * view() override { return &m_selectableTableView; }
|
||||
void viewWillAppear() override;
|
||||
void didBecomeFirstResponder() override;
|
||||
|
||||
const char * title() override { return I18n::translate(m_title); }
|
||||
|
||||
bool handleEvent(Ion::Events::Event event) override;
|
||||
|
||||
TELEMETRY_ID("ColorParameter");
|
||||
|
||||
void setRecord(Ion::Storage::Record record);
|
||||
|
||||
int numberOfRows() const override { return Palette::numberOfDataColors(); }
|
||||
KDCoordinate cellHeight() override;
|
||||
HighlightCell * reusableCell(int index) override;
|
||||
int reusableCellCount() const override { return Palette::numberOfDataColors(); } // FIXME Display issue
|
||||
void willDisplayCellForIndex(HighlightCell * cell, int index);
|
||||
private:
|
||||
bool handleEnterOnRow(int rowIndex);
|
||||
FunctionStore * functionStore();
|
||||
ExpiringPointer<Function> function();
|
||||
SelectableTableView m_selectableTableView;
|
||||
Ion::Storage::Record m_record;
|
||||
I18n::Message m_title;
|
||||
MessageTableCellWithColor m_cells[Palette::numberOfDataColors()];
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -55,6 +55,10 @@ void Function::setActive(bool active) {
|
||||
}
|
||||
}
|
||||
|
||||
void Function::setColor(KDColor color) {
|
||||
recordData()->setColor(color);
|
||||
}
|
||||
|
||||
int Function::printValue(double cursorT, double cursorX, double cursorY, char * buffer, int bufferSize, int precision, Poincare::Context * context) {
|
||||
return PoincareHelpers::ConvertFloatToText<double>(cursorY, buffer, bufferSize, precision);
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ public:
|
||||
bool isActive() const;
|
||||
KDColor color() const;
|
||||
void setActive(bool active);
|
||||
void setColor(KDColor color);
|
||||
|
||||
// Definition Interval
|
||||
virtual bool shouldClipTRangeToXRange() const { return true; } // Returns true if the function will not be displayed if t is outside x range.
|
||||
@@ -76,6 +77,7 @@ protected:
|
||||
KDColor color() const {
|
||||
return KDColor::RGB16(m_color);
|
||||
}
|
||||
void setColor(KDColor color) { m_color = color; }
|
||||
bool isActive() const { return m_active; }
|
||||
void setActive(bool active) { m_active = active; }
|
||||
private:
|
||||
|
||||
@@ -8,12 +8,12 @@ ListParameterController::ListParameterController(Responder * parentResponder, I1
|
||||
ViewController(parentResponder),
|
||||
m_selectableTableView(this, this, this, tableDelegate),
|
||||
m_record(),
|
||||
#if FUNCTION_COLOR_CHOICE
|
||||
m_colorCell(functionColorMessage),
|
||||
#endif
|
||||
m_colorCell(),
|
||||
m_enableCell(I18n::Message::ActivateDeactivate),
|
||||
m_deleteCell(deleteFunctionMessage)
|
||||
m_deleteCell(deleteFunctionMessage),
|
||||
m_colorParameterController(parentResponder, functionColorMessage)
|
||||
{
|
||||
m_colorCell.setMessage(functionColorMessage);
|
||||
}
|
||||
|
||||
const char * ListParameterController::title() {
|
||||
@@ -38,6 +38,16 @@ void ListParameterController::willDisplayCellForIndex(HighlightCell * cell, int
|
||||
if (cell == &m_enableCell) {
|
||||
SwitchView * switchView = (SwitchView *)m_enableCell.accessoryView();
|
||||
switchView->setState(function()->isActive());
|
||||
} else if(cell == &m_colorCell) {
|
||||
int index = -1;
|
||||
KDColor color = function()->color();
|
||||
for(int i = 0; i < Palette::numberOfDataColors(); i++) {
|
||||
if(color == Palette::DataColor[i]) {
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
assert(index >= 0);
|
||||
m_colorCell.setSubtitle(MessageTableCellWithColor::k_textForIndex[index]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,11 +74,7 @@ int ListParameterController::indexFromCumulatedHeight(KDCoordinate offsetY) {
|
||||
HighlightCell * ListParameterController::reusableCell(int index, int type) {
|
||||
assert(index == 0);
|
||||
assert(index < totalNumberOfCells());
|
||||
#if FUNCTION_COLOR_CHOICE
|
||||
HighlightCell * cells[] = {&m_colorCell, &m_enableCell, &m_deleteCell};
|
||||
#else
|
||||
HighlightCell * cells[] = {&m_enableCell, &m_deleteCell};
|
||||
#endif
|
||||
return cells[type];
|
||||
}
|
||||
|
||||
@@ -78,22 +84,17 @@ int ListParameterController::typeAtLocation(int i, int j) {
|
||||
|
||||
bool ListParameterController::handleEnterOnRow(int rowIndex) {
|
||||
switch (rowIndex) {
|
||||
#if FUNCTION_COLOR_CHOICE
|
||||
case 0:
|
||||
/* TODO: implement function color choice */
|
||||
case 0: {
|
||||
StackViewController * stack = (StackViewController *)(parentResponder());
|
||||
m_colorParameterController.setRecord(m_record);
|
||||
stack->push(&m_colorParameterController);
|
||||
return true;
|
||||
}
|
||||
case 1:
|
||||
#else
|
||||
case 0:
|
||||
#endif
|
||||
function()->setActive(!function()->isActive());
|
||||
m_selectableTableView.reloadData();
|
||||
return true;
|
||||
#if FUNCTION_COLOR_CHOICE
|
||||
case 2:
|
||||
#else
|
||||
case 1:
|
||||
#endif
|
||||
case 2:
|
||||
{
|
||||
assert(functionStore()->numberOfModels() > 0);
|
||||
functionStore()->removeModel(m_record);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <escher.h>
|
||||
#include "function_store.h"
|
||||
#include "color_parameter_controller.h"
|
||||
#include <apps/i18n.h>
|
||||
|
||||
namespace Shared {
|
||||
@@ -31,22 +32,17 @@ public:
|
||||
protected:
|
||||
virtual bool handleEnterOnRow(int rowIndex);
|
||||
virtual int totalNumberOfCells() const {
|
||||
#if FUNCTION_COLOR_CHOICE
|
||||
return 3;
|
||||
#else
|
||||
return 2;
|
||||
#endif
|
||||
}
|
||||
FunctionStore * functionStore();
|
||||
ExpiringPointer<Function> function();
|
||||
SelectableTableView m_selectableTableView;
|
||||
Ion::Storage::Record m_record;
|
||||
private:
|
||||
#if FUNCTION_COLOR_CHOICE
|
||||
MessageTableCellWithChevron m_colorCell;
|
||||
#endif
|
||||
MessageTableCellWithChevronAndMessage m_colorCell;
|
||||
MessageTableCellWithSwitch m_enableCell;
|
||||
MessageTableCell m_deleteCell;
|
||||
ColorParameterController m_colorParameterController;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ Values3 = "Werte V3"
|
||||
Frequencies1 = "Häufigkeiten N1"
|
||||
Frequencies2 = "Häufigkeiten N2"
|
||||
Frequencies3 = "Häufigkeiten N3"
|
||||
ImportList = "Laden einer Liste"
|
||||
Interval = " Intervall"
|
||||
Frequency = " Häufigkeit:"
|
||||
RelativeFrequency = "Relative:"
|
||||
|
||||
@@ -8,7 +8,6 @@ Values3 = "Value V3"
|
||||
Frequencies1 = "Frequency N1"
|
||||
Frequencies2 = "Frequency N2"
|
||||
Frequencies3 = "Frequency N3"
|
||||
ImportList = "Import from a list"
|
||||
Interval = " Interval "
|
||||
Frequency = " Frequency:"
|
||||
RelativeFrequency = "Relative:"
|
||||
|
||||
@@ -8,7 +8,6 @@ Values3 = "Valores V3"
|
||||
Frequencies1 = "Frecuencias N1"
|
||||
Frequencies2 = "Frecuencias N2"
|
||||
Frequencies3 = "Frecuencias N3"
|
||||
ImportList = "Importar una lista"
|
||||
Interval = " Intervalo"
|
||||
Frequency = " Frecuencia:"
|
||||
RelativeFrequency = "Relativa:"
|
||||
@@ -24,4 +23,4 @@ StandardDeviationSigma = "Desviación típica σ"
|
||||
SampleStandardDeviationS = "Desviación típica s"
|
||||
SumValues = "Suma"
|
||||
SumSquareValues = "Suma cuadrados"
|
||||
InterquartileRange = "Rango intercuartilo"
|
||||
InterquartileRange = "Rango intercuartilo"
|
||||
|
||||
@@ -8,7 +8,6 @@ Values3 = "Valeurs V3"
|
||||
Frequencies1 = "Effectifs N1"
|
||||
Frequencies2 = "Effectifs N2"
|
||||
Frequencies3 = "Effectifs N3"
|
||||
ImportList = "Importer une liste"
|
||||
Interval = " Intervalle "
|
||||
Frequency = " Effectif:"
|
||||
RelativeFrequency = "Fréquence:"
|
||||
|
||||
@@ -1,27 +1,26 @@
|
||||
StatsApp = "Statisztika"
|
||||
StatsAppCapital = "STATISZTIKA"
|
||||
HistogramTab = "Hisztogram"
|
||||
BoxTab = "Doboz"
|
||||
Values1 = "V1 értékek"
|
||||
Values2 = "V2 értékek"
|
||||
Values3 = "V3 értékek"
|
||||
Frequencies1 = "N1 Frekvencia"
|
||||
Frequencies2 = "N2 Frekvencia"
|
||||
Frequencies3 = "N3 Frekvencia"
|
||||
ImportList = "Importálás egy listáról"
|
||||
Interval = "Intervallum"
|
||||
Frequency = "Frekvencia:"
|
||||
RelativeFrequency = "Relatív:"
|
||||
HistogramSet = "Hisztogram beállítások"
|
||||
RectangleWidth = "Tálca szélessége"
|
||||
BarStart = "X kezdet"
|
||||
FirstQuartile = "Elsö kvartilis"
|
||||
Median = "Medián"
|
||||
ThirdQuartile = "Harmadik kvartilis"
|
||||
TotalFrequency = "Adatpontok száma "
|
||||
Range = "Intervallum"
|
||||
StandardDeviationSigma = "σ szórás"
|
||||
SampleStandardDeviationS = "Minta std eltérés σ"
|
||||
SumValues = "Értékek összege"
|
||||
SumSquareValues = "Négyzetértékek összege"
|
||||
InterquartileRange = "Interkvartilis tartomány"
|
||||
StatsApp = "Statisztika"
|
||||
StatsAppCapital = "STATISZTIKA"
|
||||
HistogramTab = "Hisztogram"
|
||||
BoxTab = "Doboz"
|
||||
Values1 = "V1 értékek"
|
||||
Values2 = "V2 értékek"
|
||||
Values3 = "V3 értékek"
|
||||
Frequencies1 = "N1 Frekvencia"
|
||||
Frequencies2 = "N2 Frekvencia"
|
||||
Frequencies3 = "N3 Frekvencia"
|
||||
Interval = "Intervallum"
|
||||
Frequency = "Frekvencia:"
|
||||
RelativeFrequency = "Relatív:"
|
||||
HistogramSet = "Hisztogram beállítások"
|
||||
RectangleWidth = "Tálca szélessége"
|
||||
BarStart = "X kezdet"
|
||||
FirstQuartile = "Elsö kvartilis"
|
||||
Median = "Medián"
|
||||
ThirdQuartile = "Harmadik kvartilis"
|
||||
TotalFrequency = "Adatpontok száma "
|
||||
Range = "Intervallum"
|
||||
StandardDeviationSigma = "σ szórás"
|
||||
SampleStandardDeviationS = "Minta std eltérés σ"
|
||||
SumValues = "Értékek összege"
|
||||
SumSquareValues = "Négyzetértékek összege"
|
||||
InterquartileRange = "Interkvartilis tartomány"
|
||||
|
||||
@@ -8,7 +8,6 @@ Values3 = "Valori V3"
|
||||
Frequencies1 = "Frequenze N1"
|
||||
Frequencies2 = "Frequenze N2"
|
||||
Frequencies3 = "Frequenze N3"
|
||||
ImportList = "Importare una lista"
|
||||
Interval = " Intervallo "
|
||||
Frequency = " Frequenza:"
|
||||
RelativeFrequency = "Relativa:"
|
||||
@@ -24,4 +23,4 @@ StandardDeviationSigma = "Deviazione standard σ"
|
||||
SampleStandardDeviationS = "Dev. std campionaria s"
|
||||
SumValues = "Somma"
|
||||
SumSquareValues = "Somma dei quadrati"
|
||||
InterquartileRange = "Scarto interquartile"
|
||||
InterquartileRange = "Scarto interquartile"
|
||||
|
||||
@@ -8,7 +8,6 @@ Values3 = "Waarden V3"
|
||||
Frequencies1 = "Frequenties N1"
|
||||
Frequencies2 = "Frequenties N2"
|
||||
Frequencies3 = "Frequenties N3"
|
||||
ImportList = "Importeren uit een lijst"
|
||||
Interval = " Interval "
|
||||
Frequency = " Frequentie:"
|
||||
RelativeFrequency = "Relatieve:"
|
||||
@@ -24,4 +23,4 @@ StandardDeviationSigma = "Standaardafwijking σ"
|
||||
SampleStandardDeviationS = "Standaardafwijking s"
|
||||
SumValues = "Som"
|
||||
SumSquareValues = "Som van kwadraten"
|
||||
InterquartileRange = "Interkwartielafstand"
|
||||
InterquartileRange = "Interkwartielafstand"
|
||||
|
||||
@@ -8,7 +8,6 @@ Values3 = "Valores V3"
|
||||
Frequencies1 = "Frequências N1"
|
||||
Frequencies2 = "Frequências N2"
|
||||
Frequencies3 = "Frequências N3"
|
||||
ImportList = "Importar de uma lista"
|
||||
Interval = " Intervalo"
|
||||
Frequency = " Frequência:"
|
||||
RelativeFrequency = "Relativa:"
|
||||
@@ -24,4 +23,4 @@ StandardDeviationSigma = "Desvio padrão σ"
|
||||
SampleStandardDeviationS = "Desvio padrão amostral s"
|
||||
SumValues = "Somatório"
|
||||
SumSquareValues = "Soma dos quadrados"
|
||||
InterquartileRange = "Amplitude interquartil"
|
||||
InterquartileRange = "Amplitude interquartil"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include "apps_container.h"
|
||||
|
||||
SuspendTimer::SuspendTimer() :
|
||||
Timer(k_idleBeforeSuspendDuration/Timer::TickDuration)
|
||||
Timer(GlobalPreferences::sharedGlobalPreferences()->idleBeforeSuspendSeconds()*1000/Timer::TickDuration)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ class SuspendTimer : public Timer {
|
||||
public:
|
||||
SuspendTimer();
|
||||
private:
|
||||
constexpr static int k_idleBeforeSuspendDuration = 5*60*1000; // In miliseconds
|
||||
bool fire() override;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
Unit = "Einheiten"
|
||||
UnitTimeMenu = "Zeit"
|
||||
UnitTimeSecondMenu = "Sekunde"
|
||||
UnitTimeSecond = "Sekunde"
|
||||
UnitTimeSecondMilli = "Millisekunde"
|
||||
UnitTimeSecondMicro = "Mikrosekunde"
|
||||
@@ -12,7 +11,6 @@ UnitTimeWeek = "Woche"
|
||||
UnitTimeMonth = "Monat"
|
||||
UnitTimeYear = "Jahr"
|
||||
UnitDistanceMenu = "Entfernung"
|
||||
UnitDistanceMeterMenu = "Meter"
|
||||
UnitDistanceMeterKilo = "Kilometer"
|
||||
UnitDistanceMeter = "Meter"
|
||||
UnitDistanceMeterMilli = "Millimeter"
|
||||
@@ -31,9 +29,6 @@ UnitMassGramKilo = "Kilogramm"
|
||||
UnitMassGram = "Gramm"
|
||||
UnitMassGramMilli = "Milligramm"
|
||||
UnitMassGramMicro = "Mikrogramm"
|
||||
UnitMassGramNano = "Nanogramm"
|
||||
UnitDistanceImperialMenu = "Angloamerikanisch"
|
||||
UnitMassImperialMenu = "Angloamerikanisch"
|
||||
UnitMassTonne = "Tonne"
|
||||
UnitMassOunce = "Unze"
|
||||
UnitMassPound = "Pfund"
|
||||
@@ -423,7 +418,6 @@ EscapeVelocity = "Fluchtgeschwindigkeit"
|
||||
EscapeVelocityFromEarth = "Von der Erde"
|
||||
EscapeVelocityFromMoon = "Vom Mond"
|
||||
EscapeVelocityFromSun = "Von der Sonne"
|
||||
YearLightTag = "Lichtjahr"
|
||||
Thermodynamics = "Thermodynamik"
|
||||
BoltzmannTag = "Boltzmann Konstante"
|
||||
AvogadroTag = "Avogadro-Konstante"
|
||||
@@ -466,7 +460,6 @@ MoonMassTag = "Mond"
|
||||
EarthMassTag = "Erde"
|
||||
SunMassTag = "Sonne"
|
||||
ParticleMass = "Partikel Masse"
|
||||
AstronomicalMass = "Astronomische"
|
||||
Radiuses = "Radien"
|
||||
Length = "Länge"
|
||||
Distances = "Entfernungen"
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
Unit = "Units"
|
||||
UnitTimeMenu = "Time"
|
||||
UnitTimeSecondMenu = "Second"
|
||||
UnitTimeSecond = "Second"
|
||||
UnitTimeSecondMilli = "Millisecond"
|
||||
UnitTimeSecondMicro = "Microsecond"
|
||||
@@ -12,14 +11,12 @@ UnitTimeWeek = "Week"
|
||||
UnitTimeMonth = "Month"
|
||||
UnitTimeYear = "Year"
|
||||
UnitDistanceMenu = "Distance"
|
||||
UnitDistanceMeterMenu = "Meter"
|
||||
UnitDistanceMeterKilo = "Kilometer"
|
||||
UnitDistanceMeter = "Meter"
|
||||
UnitDistanceMeterMilli = "Millimeter"
|
||||
UnitDistanceMeterMicro = "Micrometer"
|
||||
UnitDistanceMeterNano = "Nanometer"
|
||||
UnitDistanceMeterPico = "Picometer"
|
||||
UnitDistanceImperialMenu = "US Customary"
|
||||
UnitDistanceInch = "Inch"
|
||||
UnitDistanceFoot = "Foot"
|
||||
UnitDistanceYard = "Yard"
|
||||
@@ -27,13 +24,11 @@ UnitDistanceMile = "Mile"
|
||||
UnitDistanceAstronomicalUnit = "Astronomical unit"
|
||||
UnitDistanceLightYear = "Light year"
|
||||
UnitDistanceParsec = "Parsec"
|
||||
UnitMassImperialMenu = "US Customary"
|
||||
UnitMassMenu = "Mass"
|
||||
UnitMassGramKilo = "Kilogram"
|
||||
UnitMassGram = "Gram"
|
||||
UnitMassGramMilli = "Milligram"
|
||||
UnitMassGramMicro = "Microgram"
|
||||
UnitMassGramNano = "Nanogram"
|
||||
UnitMassTonne = "Metric Ton"
|
||||
UnitMassOunce = "Ounce"
|
||||
UnitMassPound = "Pound"
|
||||
@@ -423,7 +418,6 @@ EscapeVelocityFromEarth = "Of Earth"
|
||||
EscapeVelocityFromMoon = "Of Moon"
|
||||
EscapeVelocityFromSun = "Of Sun"
|
||||
SpeedOfLightTag = "Speed of light"
|
||||
YearLightTag = "One year light"
|
||||
Thermodynamics = "Thermodynamics"
|
||||
BoltzmannTag = "Boltzmann Constant"
|
||||
AvogadroTag = "Avogadro Constant"
|
||||
@@ -466,7 +460,6 @@ MoonMassTag = "Moon"
|
||||
EarthMassTag = "Earth"
|
||||
SunMassTag = "Sun"
|
||||
ParticleMass = "Particles Mass"
|
||||
AstronomicalMass = "Astronomical"
|
||||
Radiuses = "Radiuses"
|
||||
Length = "Length"
|
||||
Distances = "Distances"
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
Unit = "Units"
|
||||
UnitTimeMenu = "Time"
|
||||
UnitTimeSecondMenu = "Second"
|
||||
UnitTimeSecond = "Second"
|
||||
UnitTimeSecondMilli = "Millisecond"
|
||||
UnitTimeSecondMicro = "Microsecond"
|
||||
@@ -12,18 +11,15 @@ UnitTimeWeek = "Week"
|
||||
UnitTimeMonth = "Month"
|
||||
UnitTimeYear = "Year"
|
||||
UnitDistanceMenu = "Distance"
|
||||
UnitDistanceMeterMenu = "Meter"
|
||||
UnitDistanceMeterKilo = "Kilometer"
|
||||
UnitDistanceMeter = "Meter"
|
||||
UnitDistanceMeterMilli = "Millimeter"
|
||||
UnitDistanceMeterMicro = "Micrometer"
|
||||
UnitDistanceMeterNano = "Nanometer"
|
||||
UnitDistanceMeterPico = "Picometer"
|
||||
UnitDistanceImperialMenu = "US Customary"
|
||||
UnitDistanceAstronomicalUnit = "Astronomical unit"
|
||||
UnitDistanceLightYear = "Light year"
|
||||
UnitDistanceParsec = "Parsec"
|
||||
UnitMassImperialMenu = "US Customary"
|
||||
UnitDistanceMile = "Milla"
|
||||
UnitDistanceYard = "Yardas"
|
||||
UnitDistanceFoot = "Pie"
|
||||
@@ -33,7 +29,6 @@ UnitMassGramKilo = "Kilogram"
|
||||
UnitMassGram = "Gram"
|
||||
UnitMassGramMilli = "Milligram"
|
||||
UnitMassGramMicro = "Microgram"
|
||||
UnitMassGramNano = "Nanogram"
|
||||
UnitMassTonne = "Tonne"
|
||||
UnitMassOunce = "Onza"
|
||||
UnitMassPound = "Libra"
|
||||
@@ -415,7 +410,6 @@ AlphaElementUbn = "Ubn - Unbinilio (120)"
|
||||
Speed = "Velocidad"
|
||||
SpeedOfLightTag = "Velocidad de la luz"
|
||||
SpeedOfSound = "La velocidad del sonido"
|
||||
YearLightTag = "Un año de luz"
|
||||
Thermodynamics = "Termodinámica"
|
||||
SpeedOfSound0Tag = "Nivel del mar, 20 ° C"
|
||||
SpeedOfSoundWaterTag = "En el agua"
|
||||
@@ -466,7 +460,6 @@ MoonMassTag = "Luna"
|
||||
EarthMassTag = "Tierra"
|
||||
SunMassTag = "Sol"
|
||||
ParticleMass = "Misa de las partículas"
|
||||
AstronomicalMass = "Astronómica"
|
||||
Radiuses = "Radios"
|
||||
Length = "Lenght"
|
||||
Distances = "Distancias"
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
Unit = "Unités"
|
||||
UnitTimeMenu = "Temps"
|
||||
UnitTimeSecondMenu = "Seconde"
|
||||
UnitTimeSecond = "Seconde"
|
||||
UnitTimeSecondMilli = "Milliseconde"
|
||||
UnitTimeSecondMicro = "Microseconde"
|
||||
@@ -12,14 +11,12 @@ UnitTimeWeek = "Semaine"
|
||||
UnitTimeMonth = "Mois"
|
||||
UnitTimeYear = "Année"
|
||||
UnitDistanceMenu = "Distance"
|
||||
UnitDistanceMeterMenu = "Mètre"
|
||||
UnitDistanceMeterKilo = "Kilomètre"
|
||||
UnitDistanceMeter = "Mètre"
|
||||
UnitDistanceMeterMilli = "Millimètre"
|
||||
UnitDistanceMeterMicro = "Micromètre"
|
||||
UnitDistanceMeterNano = "Nanomètre"
|
||||
UnitDistanceMeterPico = "Picomètre"
|
||||
UnitDistanceImperialMenu = "US Customary"
|
||||
UnitDistanceInch = "Inch"
|
||||
UnitDistanceFoot = "Foot"
|
||||
UnitDistanceYard = "Yard"
|
||||
@@ -27,7 +24,6 @@ UnitDistanceMile = "Mile"
|
||||
UnitDistanceAstronomicalUnit = "Unité astronomique"
|
||||
UnitDistanceLightYear = "Année-lumière"
|
||||
UnitDistanceParsec = "Parsec"
|
||||
UnitMassImperialMenu = "US Customary"
|
||||
UnitDistanceMile = "Mile"
|
||||
UnitDistanceYard = "Yard"
|
||||
UnitDistanceFoot = "Pied"
|
||||
@@ -37,7 +33,6 @@ UnitMassGramKilo = "Kilogramme"
|
||||
UnitMassGram = "Gramme"
|
||||
UnitMassGramMilli = "Milligramme"
|
||||
UnitMassGramMicro = "Microgramme"
|
||||
UnitMassGramNano = "Nanogramme"
|
||||
UnitMassTonne = "Tonne"
|
||||
UnitMassOunce = "Once"
|
||||
UnitMassPound = "Livre"
|
||||
@@ -423,7 +418,6 @@ SpeedOfSoundWaterTag = "Dans l'eau"
|
||||
SpeedOfSoundSteelTag = "Dans l'acier"
|
||||
SpeedOfSoundGlassTag = "Dans le verre"
|
||||
SpeedOfLightTag = "Vitesse de la lumière"
|
||||
YearLightTag = "Année lumière"
|
||||
Thermodynamics = "Thermodynamique"
|
||||
BoltzmannTag = "Constante de Boltzmann"
|
||||
AvogadroTag = "Constante d'Avogadro"
|
||||
@@ -470,7 +464,6 @@ MoonMassTag = "Lune"
|
||||
EarthMassTag = "Terre"
|
||||
SunMassTag = "Soleil"
|
||||
ParticleMass = "Masses des Particules"
|
||||
AstronomicalMass = "Astronomiques"
|
||||
Radiuses = "Rayons"
|
||||
Length = "Longueur"
|
||||
Distances = "Distances"
|
||||
|
||||
1031
apps/toolbox.hu.i18n
1031
apps/toolbox.hu.i18n
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,5 @@
|
||||
Unit = "Unità"
|
||||
UnitTimeMenu = "Tempo"
|
||||
UnitTimeSecondMenu = "Secondo"
|
||||
UnitTimeSecond = "Secondo"
|
||||
UnitTimeSecondMilli = "Millisecondo"
|
||||
UnitTimeSecondMicro = "Microsecondo"
|
||||
@@ -12,18 +11,15 @@ UnitTimeWeek = "Settimana"
|
||||
UnitTimeMonth = "Mese"
|
||||
UnitTimeYear = "Anno"
|
||||
UnitDistanceMenu = "Distanza"
|
||||
UnitDistanceMeterMenu = "Metro"
|
||||
UnitDistanceMeterKilo = "Chilometro"
|
||||
UnitDistanceMeter = "Metro"
|
||||
UnitDistanceMeterMilli = "Millimetro"
|
||||
UnitDistanceMeterMicro = "Micrometro"
|
||||
UnitDistanceMeterNano = "Nanometro"
|
||||
UnitDistanceMeterPico = "Picometro"
|
||||
UnitDistanceImperialMenu = "US Customary"
|
||||
UnitDistanceAstronomicalUnit = "Unità astronomica"
|
||||
UnitDistanceLightYear = "Anno luce"
|
||||
UnitDistanceParsec = "Parsec"
|
||||
UnitMassImperialMenu = "US Customary"
|
||||
UnitDistanceMile = "Miglio"
|
||||
UnitDistanceYard = "Yard"
|
||||
UnitDistanceFoot = "Piede"
|
||||
@@ -33,7 +29,6 @@ UnitMassGramKilo = "Kilogrammo"
|
||||
UnitMassGram = "Grammo"
|
||||
UnitMassGramMilli = "Milligrammo"
|
||||
UnitMassGramMicro = "Microgrammo"
|
||||
UnitMassGramNano = "Nanogrammo"
|
||||
UnitMassTonne = "Tonnellata"
|
||||
UnitMassOunce = "Oncia"
|
||||
UnitMassPound = "Libbra"
|
||||
@@ -423,7 +418,6 @@ EscapeVelocityFromEarth = "Della terra"
|
||||
EscapeVelocityFromMoon = "Di luna"
|
||||
EscapeVelocityFromSun = "Di sole"
|
||||
SpeedOfLightTag = "Velocità della luce"
|
||||
YearLightTag = "Un anno di luce"
|
||||
Thermodynamics = "Termodinamica"
|
||||
BoltzmannTag = "Costante di Boltzmann"
|
||||
AvogadroTag = "Costanto di Avogadro"
|
||||
@@ -466,7 +460,6 @@ MoonMassTag = "Luna"
|
||||
EarthMassTag = "Terra"
|
||||
SunMassTag = "Sole"
|
||||
ParticleMass = "Massa delle particelle"
|
||||
AstronomicalMass = "Astronomico"
|
||||
Radiuses = "Raggi"
|
||||
Length = "Lunghezza"
|
||||
Distances = "Distanze"
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
Unit = "Eenheden"
|
||||
UnitTimeMenu = "Tijd"
|
||||
UnitTimeSecondMenu = "Seconde"
|
||||
UnitTimeSecond = "Seconde"
|
||||
UnitTimeSecondMilli = "MilliSeconde"
|
||||
UnitTimeSecondMicro = "Microseconde"
|
||||
@@ -12,18 +11,15 @@ UnitTimeWeek = "Week"
|
||||
UnitTimeMonth = "Maand"
|
||||
UnitTimeYear = "Jaar"
|
||||
UnitDistanceMenu = "Afstand"
|
||||
UnitDistanceMeterMenu = "Meter"
|
||||
UnitDistanceMeterKilo = "Kilometer"
|
||||
UnitDistanceMeter = "Meter"
|
||||
UnitDistanceMeterMilli = "Millimeter"
|
||||
UnitDistanceMeterMicro = "Micrometer"
|
||||
UnitDistanceMeterNano = "Nanometer"
|
||||
UnitDistanceMeterPico = "Picometer"
|
||||
UnitDistanceImperialMenu = "US Customary"
|
||||
UnitDistanceAstronomicalUnit = "Astronomische eenheid"
|
||||
UnitDistanceLightYear = "Lichtjaar"
|
||||
UnitDistanceParsec = "Parsec"
|
||||
UnitMassImperialMenu = "US Customary"
|
||||
UnitDistanceMile = "Mijl"
|
||||
UnitDistanceYard = "Yard"
|
||||
UnitDistanceFoot = "Voet"
|
||||
@@ -33,7 +29,6 @@ UnitMassGramKilo = "Kilogram"
|
||||
UnitMassGram = "Gram"
|
||||
UnitMassGramMilli = "Milligram"
|
||||
UnitMassGramMicro = "Microgram"
|
||||
UnitMassGramNano = "Nanogram"
|
||||
UnitMassTonne = "Ton"
|
||||
UnitMassOunce = "Ons"
|
||||
UnitMassPound = "Pond"
|
||||
@@ -423,7 +418,6 @@ EscapeVelocityFromEarth = "Van Aarde"
|
||||
EscapeVelocityFromMoon = "Van Maan"
|
||||
EscapeVelocityFromSun = "Van de zon"
|
||||
SpeedOfLightTag = "Lichtsnelheid"
|
||||
YearLightTag = "Een jaar licht"
|
||||
Thermodynamics = "Thermodynamica"
|
||||
BoltzmannTag = "Boltzmannconstante"
|
||||
AvogadroTag = "Avogadroconstante"
|
||||
@@ -466,7 +460,6 @@ MoonMassTag = "Maan"
|
||||
EarthMassTag = "Aarde"
|
||||
SunMassTag = "Zon"
|
||||
ParticleMass = "Deeltjesmassa"
|
||||
AstronomicalMass = "Astronomical"
|
||||
Radiuses = "Radiuses"
|
||||
Length = "Lengte"
|
||||
Distances = "Afstanden"
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
Unit = "Unidade"
|
||||
UnitTimeMenu = "Tempo"
|
||||
UnitTimeSecondMenu = "Segundo"
|
||||
UnitTimeSecond = "Segundo"
|
||||
UnitTimeSecondMilli = "Milisegundo"
|
||||
UnitTimeSecondMicro = "Microsegundo"
|
||||
@@ -12,18 +11,15 @@ UnitTimeWeek = "Semana"
|
||||
UnitTimeMonth = "Mês"
|
||||
UnitTimeYear = "Ano"
|
||||
UnitDistanceMenu = "Distância"
|
||||
UnitDistanceMeterMenu = "Metro"
|
||||
UnitDistanceMeterKilo = "Quilómetro"
|
||||
UnitDistanceMeter = "Metro"
|
||||
UnitDistanceMeterMilli = "Milímetro"
|
||||
UnitDistanceMeterMicro = "Micrómetro"
|
||||
UnitDistanceMeterNano = "Nanómetro"
|
||||
UnitDistanceMeterPico = "Picómetro"
|
||||
UnitDistanceImperialMenu = "US Customary"
|
||||
UnitDistanceAstronomicalUnit = "Unidade astronómica"
|
||||
UnitDistanceLightYear = "Ano-luz"
|
||||
UnitDistanceParsec = "Parsec"
|
||||
UnitMassImperialMenu = "US Customary"
|
||||
UnitDistanceMile = "Milha"
|
||||
UnitDistanceYard = "Jarda"
|
||||
UnitDistanceFoot = "Pé"
|
||||
@@ -33,7 +29,6 @@ UnitMassGramKilo = "Quilograma"
|
||||
UnitMassGram = "Grama"
|
||||
UnitMassGramMilli = "Miligrama"
|
||||
UnitMassGramMicro = "Micrograma"
|
||||
UnitMassGramNano = "Nanograma"
|
||||
UnitMassTonne = "Tonelada"
|
||||
UnitMassOunce = "Onça"
|
||||
UnitMassPound = "Libra"
|
||||
@@ -423,7 +418,6 @@ EscapeVelocity = "Velocidade de Fuga"
|
||||
EscapeVelocityFromEarth = "Fuga da Terra"
|
||||
EscapeVelocityFromMoon = "De Lua"
|
||||
EscapeVelocityFromSun = "Do Sol"
|
||||
YearLightTag = "Luz de um ano"
|
||||
Thermodynamics = "Termodinâmica"
|
||||
BoltzmannTag = "Constante Boltzmann"
|
||||
AvogadroTag = "Constante Avogadro"
|
||||
@@ -466,7 +460,6 @@ MoonMassTag = "Lua"
|
||||
EarthMassTag = "Terra"
|
||||
SunMassTag = "Sol"
|
||||
ParticleMass = "Massa de Partículas"
|
||||
AstronomicalMass = "Astronômico"
|
||||
Radiuses = "Raio"
|
||||
Length = "Comprimento"
|
||||
Distances = "Distâncias"
|
||||
|
||||
@@ -6,9 +6,7 @@ ConnectedMessage4 = "Drücken Sie die Zurück-Taste am"
|
||||
ConnectedMessage5 = "Taschenrechner oder Kabel abziehen,"
|
||||
ConnectedMessage6 = "um die Verbindung zu trennen."
|
||||
DfuStatus = "Status des Rechners:"
|
||||
DfuStatusProtected = "GESCHÜTZT"
|
||||
DfuStatusUnprotected = "UNGESCHÜTZT"
|
||||
USBProtectionLevel0 = "Standardschutz"
|
||||
USBProtectionLevel1 = "Omega Schutz"
|
||||
USBProtectionLevel2 = "Systemschutz"
|
||||
USBProtectionReactivated = "USB-Schutz wurde wieder aktiviert"
|
||||
|
||||
@@ -6,9 +6,7 @@ ConnectedMessage4 = "Press the BACK key of your"
|
||||
ConnectedMessage5 = "calculator or unplug it to"
|
||||
ConnectedMessage6 = "disconnect it."
|
||||
DfuStatus = "Calculator status:"
|
||||
DfuStatusProtected = "PROTECTED"
|
||||
DfuStatusUnprotected = "UNPROTECTED"
|
||||
USBProtectionLevel0 = "Default Protection"
|
||||
USBProtectionLevel1 = "Omega Protection"
|
||||
USBProtectionLevel2 = "System Protection"
|
||||
USBProtectionReactivated = "USB Protection reactivated"
|
||||
|
||||
@@ -6,9 +6,7 @@ ConnectedMessage4 = "Pulse el botón RETURN de la"
|
||||
ConnectedMessage5 = "calculadora o desenchúfela para"
|
||||
ConnectedMessage6 = "desconectarla."
|
||||
DfuStatus = "Estado de la calculadora:"
|
||||
DfuStatusProtected = "PROTEGIDO"
|
||||
DfuStatusUnprotected = "DESABRIGADO"
|
||||
USBProtectionLevel0 = "Protección predeterminada"
|
||||
USBProtectionLevel1 = "Protección Omega"
|
||||
USBProtectionLevel2 = "Protección del sistema"
|
||||
USBProtectionReactivated = "La protección de la calculadora ha sido reactivada"
|
||||
@@ -6,9 +6,7 @@ ConnectedMessage4 = "Appuyez sur la touche RETOUR"
|
||||
ConnectedMessage5 = "de la calculatrice ou débranchez-la"
|
||||
ConnectedMessage6 = "pour la déconnecter."
|
||||
DfuStatus = "Etat de la calculatrice:"
|
||||
DfuStatusProtected = "PROTÉGÉE"
|
||||
DfuStatusUnprotected = "NON PROTÉGÉE"
|
||||
USBProtectionLevel0 = "Default Protection"
|
||||
USBProtectionLevel1 = "Omega Protection"
|
||||
USBProtectionLevel2 = "System Protection"
|
||||
USBProtectionReactivated = "La protection USB a été réactivée"
|
||||
@@ -1,14 +1,12 @@
|
||||
USBConnected = "A SZÁMOLÓGÉP CSATLAKOZTATVA VAN"
|
||||
ConnectedMessage1 = ""
|
||||
ConnectedMessage2 = "Adat másolásához csatlakozzon"
|
||||
ConnectedMessage3 = "fel getomega.dev/ide ra."
|
||||
ConnectedMessage4 = "Nyomjon majd a VISSZA gombra"
|
||||
ConnectedMessage5 = "vagy huzza ki a kábelt azért"
|
||||
ConnectedMessage6 = "hogy a másolás véget érjen."
|
||||
DfuStatus = "Számológép állapota:"
|
||||
DfuStatusProtected = "VÉDETT"
|
||||
DfuStatusUnprotected = "VÉDTELEN"
|
||||
USBProtectionLevel0 = "Alapértelmezett védelem"
|
||||
USBProtectionLevel1 = "Omega védelem"
|
||||
USBProtectionLevel2 = "Rendszervédelem"
|
||||
USBProtectionReactivated = "A védelem újra aktiválva"
|
||||
USBConnected = "A SZÁMOLÓGÉP CSATLAKOZTATVA VAN"
|
||||
ConnectedMessage1 = ""
|
||||
ConnectedMessage2 = "Adat másolásához csatlakozzon"
|
||||
ConnectedMessage3 = "fel getomega.dev/ide ra."
|
||||
ConnectedMessage4 = "Nyomjon majd a VISSZA gombra"
|
||||
ConnectedMessage5 = "vagy huzza ki a kábelt azért"
|
||||
ConnectedMessage6 = "hogy a másolás véget érjen."
|
||||
DfuStatus = "Számológép állapota:"
|
||||
DfuStatusUnprotected = "VÉDTELEN"
|
||||
USBProtectionLevel0 = "Alapértelmezett védelem"
|
||||
USBProtectionLevel1 = "Omega védelem"
|
||||
USBProtectionLevel2 = "Rendszervédelem"
|
||||
|
||||
@@ -6,9 +6,7 @@ ConnectedMessage4 = "Premere sul tasto INDIETRO della"
|
||||
ConnectedMessage5 = "calcolatrice o scollegatela per"
|
||||
ConnectedMessage6 = "disconnetterla."
|
||||
DfuStatus = "Stato della calcolatrice:"
|
||||
DfuStatusProtected = "PROTETTO"
|
||||
DfuStatusUnprotected = "INDIFESO"
|
||||
USBProtectionLevel0 = "Protezione predefinita"
|
||||
USBProtectionLevel1 = "Protezione Omega"
|
||||
USBProtectionLevel2 = "Protezione del sistema"
|
||||
USBProtectionReactivated = "Protezione riattivata"
|
||||
|
||||
@@ -6,9 +6,7 @@ ConnectedMessage4 = "Druk op de TERUG toets van je"
|
||||
ConnectedMessage5 = "rekenmachine of verwijder de"
|
||||
ConnectedMessage6 = " kabel om hem los te koppelen."
|
||||
DfuStatus = "Rekenmachine status:"
|
||||
DfuStatusProtected = "BESCHERMD"
|
||||
DfuStatusUnprotected = "NIET BESCHERMD"
|
||||
USBProtectionLevel0 = "Standaardbeveiliging"
|
||||
USBProtectionLevel1 = "Omega Bescherming"
|
||||
USBProtectionLevel2 = "Systeembeveiliging"
|
||||
USBProtectionReactivated = "USB-bescherming is geactiveerd"
|
||||
|
||||
@@ -6,9 +6,7 @@ ConnectedMessage4 = "Pressione o botão RETURN na"
|
||||
ConnectedMessage5 = "calculadora ou desligue-a para a"
|
||||
ConnectedMessage6 = "desconectar."
|
||||
DfuStatus = "Status da calculadora:"
|
||||
DfuStatusProtected = "PROTEGIDO"
|
||||
DfuStatusUnprotected = "DESPROTEGIDO"
|
||||
USBProtectionLevel0 = "Proteção padrão"
|
||||
USBProtectionLevel1 = "Proteção Ômega"
|
||||
USBProtectionLevel2 = "Proteção do sistema"
|
||||
USBProtectionReactivated = "Proteção reativada"
|
||||
|
||||
363
build/utilities/translations_clean.py
Normal file
363
build/utilities/translations_clean.py
Normal file
@@ -0,0 +1,363 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Remove all unused translations to save flash space."""
|
||||
# Builtins imports
|
||||
import os
|
||||
import re
|
||||
import argparse
|
||||
|
||||
|
||||
# Initialize the parser
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Remove unused translations from the i18n file to save flash \
|
||||
space.", epilog="You can use this script without arguments"
|
||||
)
|
||||
# Add arguments to the parser
|
||||
parser.add_argument("--base-path", default=".",
|
||||
help="The base path of the files")
|
||||
parser.add_argument("--no-recursive", default=False, action="store_true",
|
||||
help="Disable finding the files recursively")
|
||||
parser.add_argument("--dry-run", default=False, action="store_true",
|
||||
help="Disable saving the i18n files")
|
||||
# Parse command line arguments
|
||||
args = parser.parse_args()
|
||||
|
||||
# Initialize the settings
|
||||
BASE_PATH = args.base_path
|
||||
FIND_RECURSIVE = not args.no_recursive
|
||||
DRYRUN = args.dry_run
|
||||
# Don't add / at the end of the path
|
||||
IGNORE_PATHS = [
|
||||
"./output", "./.git", "./.mypy_cache",
|
||||
"./ion/src/simulator/external/sdl",
|
||||
]
|
||||
IGNORE_PATHS_CONTENTS = [
|
||||
"__pycache__", ".png", ".esc", ".ttf", ".ico", ".jpg", ".jar", ".icn",
|
||||
".bnr", ".i18n"
|
||||
]
|
||||
|
||||
# If the key contain something that's in this list, keep it to prevent code breaking
|
||||
KEEP_KEY_IF_CONTAIN = ["Language", "Country"]
|
||||
|
||||
|
||||
def get_all_files_in_directory(directory: str)\
|
||||
-> list[str]:
|
||||
"""Get all files in the given directory recursively.
|
||||
|
||||
Args:
|
||||
directory (str): The directory
|
||||
|
||||
Returns:
|
||||
List[str]: The list of files in the directory
|
||||
|
||||
"""
|
||||
# Initialize the list of files
|
||||
files = []
|
||||
# Iterate over all files in the directory
|
||||
for i in os.listdir(directory):
|
||||
# Add the current directory to the file name
|
||||
i = f'{directory}/{i}'
|
||||
# If the file is a directory
|
||||
if FIND_RECURSIVE and os.path.isdir(i):
|
||||
# Iter the directory and add the files to the list
|
||||
files.extend(get_all_files_in_directory(i))
|
||||
# Else the file is a file
|
||||
else:
|
||||
# Add the file to the list
|
||||
files.append(i)
|
||||
# Return the list of files
|
||||
return files
|
||||
|
||||
|
||||
def get_files(directory: str) -> list[str]:
|
||||
"""Get all files in the directory recursively with ignoring list.
|
||||
|
||||
Args:
|
||||
directory (str): The start directory
|
||||
|
||||
Returns:
|
||||
List[str]: The list of files
|
||||
"""
|
||||
# Initialize the list of files
|
||||
files = []
|
||||
# Iterate over the directory
|
||||
for filename in os.listdir(directory):
|
||||
# Add the full path to the directory/file
|
||||
filename = f'{directory}/{filename}'
|
||||
# Exclude path in IGNORE_PATHS
|
||||
if filename in IGNORE_PATHS:
|
||||
continue
|
||||
# Exclude paths in IGNORE_PATHS_CONTENTS
|
||||
if any(extension in filename for extension in IGNORE_PATHS_CONTENTS):
|
||||
continue
|
||||
# If it is a directory, find recursively the files into it
|
||||
if os.path.isdir(filename):
|
||||
files.extend(get_files(filename))
|
||||
else:
|
||||
files.append(filename)
|
||||
# Return the file list
|
||||
return files
|
||||
|
||||
|
||||
def get_keys_in_i18n_file(filename: str) -> list[list[str]]:
|
||||
"""Return a list of keys in the file.
|
||||
|
||||
Args:
|
||||
filename (str): The name of the file to read
|
||||
|
||||
Returns:
|
||||
List[list[str]]: The keys in the file
|
||||
|
||||
"""
|
||||
# Initialize the list of keys in the file
|
||||
keys: list[list[str]] = []
|
||||
# Open the file read only
|
||||
with open(filename, 'r', encoding='utf-8') as file_read:
|
||||
# Read the content of the file line by line
|
||||
for line in file_read.readlines():
|
||||
# Ignore commented lines
|
||||
if re.match(r"^#(.*)$", line):
|
||||
continue
|
||||
# Ignore lines without =
|
||||
if '=' not in line:
|
||||
continue
|
||||
# Get the key by spliting the line by =
|
||||
key = line.split("=")[0]
|
||||
# Remove spaces from the start of the key
|
||||
while key[0] == " ":
|
||||
key = key[1:]
|
||||
# Remove spaces from the end of the key
|
||||
while key[-1] == " ":
|
||||
key = key[:-1]
|
||||
# Get generic filename into a list separated by dots
|
||||
generic_filename_list = filename.split(".")[:-2]
|
||||
# Get if the locale is universal
|
||||
locale = filename.split(".")[-2]
|
||||
# Get the filename as string with a trailing dot at the end
|
||||
generic_filename = "".join(f'{i}.' for i in generic_filename_list)
|
||||
# Remove trailing dot from the end of the generic filename
|
||||
generic_filename = generic_filename[:-1]
|
||||
# Add the key and the generic filename to the list of keys
|
||||
keys.append([key, generic_filename, locale])
|
||||
return keys
|
||||
|
||||
|
||||
def list_keys_in_i18n_file_list(i18n_files: list[str]) -> list[list[str]]:
|
||||
"""List all keys in the i18n files.
|
||||
|
||||
Args:
|
||||
i18n_files (list[str]): I18n files list
|
||||
|
||||
Returns:
|
||||
List[list[str]]: The dictionnary of keys in the i18n files by
|
||||
locale.
|
||||
|
||||
"""
|
||||
# Initialize the list of keys in the i18n files
|
||||
keys_dict: list[list[str]] = []
|
||||
# Iterate on the file list
|
||||
for actual_file in i18n_files:
|
||||
# Get the keys in the file and add them to the list
|
||||
keys_dict.extend(get_keys_in_i18n_file(actual_file))
|
||||
# Return the dictionary of keys in the i18n files sorted by locale
|
||||
return keys_dict
|
||||
|
||||
|
||||
def extract_keys_from_line(line: str) -> list[str]:
|
||||
"""Extract keys from a line.
|
||||
|
||||
Args:
|
||||
line (str): The line to extract keys from
|
||||
|
||||
Returns:
|
||||
list[str]: The extracted keys
|
||||
"""
|
||||
# Initialize the list of separator to separate the key from the part
|
||||
keys_separator: list[str] = ["}", ":", ";", ",", " ", ")"]
|
||||
# Initialize the list of keys
|
||||
keys: list[str] = []
|
||||
# Split the line by ::
|
||||
line_splitted: list[str] = line.split("::")
|
||||
# Initialize loop variables
|
||||
# The last part (used inside the loop)
|
||||
last_part: str = ""
|
||||
# Mark the next line contain the key
|
||||
save_next_line: bool = False
|
||||
# The key part
|
||||
key_parts: list[str] = []
|
||||
# Iterate over the splitted line
|
||||
for part in line_splitted:
|
||||
# print(part)
|
||||
if save_next_line:
|
||||
key_parts.append(part)
|
||||
save_next_line = False
|
||||
# If the actual part is Message and the last part contain I18n
|
||||
# (I18n::Message), the next part will contain the key name
|
||||
# TODO: Improve catching
|
||||
if part == "Message" and "I18n" in last_part:
|
||||
save_next_line = True
|
||||
# Save the current part into the last part
|
||||
# (loop iteration is finished)
|
||||
last_part = part
|
||||
# Get the key from the key part
|
||||
# TODO: Improve catching
|
||||
# Iterate over all the keys in the line
|
||||
for actual_key in key_parts:
|
||||
# Initialize real key variable
|
||||
key_real: str = actual_key
|
||||
for separator_to_test in keys_separator:
|
||||
key_separated: list[str] = key_real.split(separator_to_test)
|
||||
# print(key_real, separator_to_test, key_separated)
|
||||
# If the key was splitted, save the separated key
|
||||
if len(key_separated) > 1:
|
||||
key_real = key_separated[0]
|
||||
if key_real:
|
||||
keys.append(key_real)
|
||||
return keys
|
||||
|
||||
|
||||
def keys_from_file_list(files: list[str]) -> list[str]:
|
||||
"""Get an array of keys from files.
|
||||
|
||||
Args:
|
||||
files (list[str]): The list of files to read
|
||||
|
||||
Returns:
|
||||
list[str]: The keys
|
||||
"""
|
||||
# Initialize the list of keys from the files
|
||||
keys: list[str] = []
|
||||
# Iterate over the file list
|
||||
for filename in files:
|
||||
# Read the file contents into "content" variable
|
||||
with open(filename, 'r', encoding="utf-8") as file_obj:
|
||||
# Store the contents of the file
|
||||
content = file_obj.read()
|
||||
# Iterate over the file contents
|
||||
for line in content.split("\n"):
|
||||
# Get if the line contains an I18n key
|
||||
if "I18n::Message" in line:
|
||||
# Extract the keys from the line
|
||||
keys.extend(extract_keys_from_line(line))
|
||||
return keys
|
||||
|
||||
|
||||
def get_i18n_files(directory: str = '.') -> list[str]:
|
||||
"""Get the list of i18n files in the given directory.
|
||||
|
||||
Args:
|
||||
directory (str, optional): The directory to find the i18n files.
|
||||
Defaults to '.'.
|
||||
|
||||
Returns:
|
||||
list[str]: The list of i18n files in a dictionary of languages.
|
||||
|
||||
"""
|
||||
# Get all files in the directory recursively
|
||||
files = get_all_files_in_directory(directory)
|
||||
# Return only i18n files
|
||||
return [i for i in files if ".i18n" in i]
|
||||
|
||||
|
||||
def get_unused_keys(file_keys: list[str], i18n_keys: list[list[str]]) -> list[list[str]]:
|
||||
"""Get unused keys.
|
||||
|
||||
Args:
|
||||
file_keys (list[str]): The keys in the source files
|
||||
i18n_keys (list[list[str]]): The keys in the i18n files
|
||||
|
||||
Returns:
|
||||
list[list[str]]: The unused keys
|
||||
"""
|
||||
# Initialize the list of unused keys
|
||||
unused_keys: list[list[str]] = []
|
||||
# Iterate over the i18n key definitions
|
||||
for key_i18n_actual in i18n_keys:
|
||||
# Get if the key is used, and mark it as used if it is in the kepping
|
||||
# list
|
||||
key_used = next(
|
||||
(
|
||||
True
|
||||
for string_to_test in KEEP_KEY_IF_CONTAIN
|
||||
if string_to_test in key_i18n_actual[0]
|
||||
),
|
||||
any(key_i18n_actual[0] == file_key for file_key in file_keys),
|
||||
)
|
||||
|
||||
# If the key is not used, add it to the list
|
||||
if not key_used:
|
||||
if key_i18n_actual not in unused_keys:
|
||||
print(f"{key_i18n_actual[0]} unused")
|
||||
unused_keys.append(key_i18n_actual)
|
||||
return unused_keys
|
||||
|
||||
|
||||
def remove_keys_from_i18n_files(unused_keys: list[list[str]]):
|
||||
"""Remove unused keys from i18n files.
|
||||
|
||||
Args:
|
||||
unused_keys (list[list[str]]): The list of keys to remove
|
||||
"""
|
||||
# Initialize the dictionary of files
|
||||
# (to prevent intensive writing to disk)
|
||||
files_to_write: dict[str, str] = {}
|
||||
# Iterate over the keys to remove
|
||||
for key in unused_keys:
|
||||
key_name_to_remove = key[0]
|
||||
filename_generic = key[1]
|
||||
locale = key[2]
|
||||
# Get the filename of from the generic filename
|
||||
filename = f'{filename_generic}.{locale}.i18n'
|
||||
# If the file is not in the dictionary, add it
|
||||
if filename not in files_to_write:
|
||||
# Save the file contents
|
||||
with open(filename, 'r', encoding='utf8') as file_read:
|
||||
files_to_write[filename] = file_read.read()
|
||||
# Split the file by new lines
|
||||
file_splitted = files_to_write[filename].split("\n")
|
||||
# Iterate over the file contents
|
||||
for line, value in enumerate(file_splitted):
|
||||
# Ignore lines without =
|
||||
if '=' not in value:
|
||||
continue
|
||||
# Get the key from the line
|
||||
key_to_check: str = value.split("=")[0]
|
||||
# Remove spaces from the start of the key
|
||||
while key_to_check[0] == " ":
|
||||
key_to_check = key_to_check[1:]
|
||||
# Remove spaces from the end of the key
|
||||
while key_to_check[-1] == " ":
|
||||
key_to_check = key_to_check[:-1]
|
||||
# If the key is the key to remove, remove it
|
||||
if key_to_check == key_name_to_remove:
|
||||
del file_splitted[line]
|
||||
break
|
||||
file_str = "".join(line + "\n" for line in file_splitted)
|
||||
# Remove double line return
|
||||
while file_str[-2:] == '\n\n':
|
||||
file_str = file_str[:-1]
|
||||
files_to_write[filename] = file_str
|
||||
# When the loop is end, write the files
|
||||
for actual_file, content_to_write in files_to_write.items():
|
||||
with open(actual_file, 'w', encoding='utf-8') as file_to_write:
|
||||
file_to_write.write(content_to_write)
|
||||
# print(actual_file, content_to_write)
|
||||
|
||||
|
||||
def main():
|
||||
"""Execute the program."""
|
||||
# Get the file list
|
||||
file_list = get_files(BASE_PATH)
|
||||
# Get the keys in the file list
|
||||
files_keys = keys_from_file_list(file_list)
|
||||
# Get i18n files list
|
||||
i18n_files = get_i18n_files(BASE_PATH)
|
||||
# Get keys from i18n files
|
||||
i18n_files_keys = list_keys_in_i18n_file_list(i18n_files)
|
||||
# Get unused keys
|
||||
unused_keys = get_unused_keys(files_keys, i18n_files_keys)
|
||||
# If dryrun is disabled, remove the keys definitions from the i18n files
|
||||
if not DRYRUN:
|
||||
remove_keys_from_i18n_files(unused_keys)
|
||||
|
||||
|
||||
main()
|
||||
@@ -17,7 +17,7 @@ public:
|
||||
static constexpr int TickDuration = 300; // In Miliseconds
|
||||
Timer(uint32_t period); // Period is in ticks
|
||||
bool tick();
|
||||
void reset();
|
||||
void reset(uint32_t NewPeriod = -1);
|
||||
protected:
|
||||
virtual bool fire() = 0;
|
||||
uint32_t m_period;
|
||||
|
||||
@@ -16,6 +16,9 @@ bool Timer::tick() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void Timer::reset() {
|
||||
void Timer::reset(uint32_t NewPeriod) {
|
||||
if(NewPeriod != -1){
|
||||
m_period = NewPeriod;
|
||||
}
|
||||
m_numberOfTicksBeforeFire = m_period;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ bool isInitialized();
|
||||
void shutdown();
|
||||
void setBrightness(uint8_t b);
|
||||
uint8_t brightness();
|
||||
const int NumberOfStepsPerShortcut = 4;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
218
ion/include/ion/internal_storage.h
Normal file
218
ion/include/ion/internal_storage.h
Normal file
@@ -0,0 +1,218 @@
|
||||
#ifndef ION_INTERNAL_STORAGE_H
|
||||
#define ION_INTERNAL_STORAGE_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "storage.h"
|
||||
|
||||
namespace Ion {
|
||||
|
||||
/* Storage : | Magic | Record1 | Record2 | ... | Magic |
|
||||
* | Magic | Size1(uint16_t) | FullName1 | Body1 | Size2(uint16_t) | FullName2 | Body2 | ... | Magic |
|
||||
*
|
||||
* A record's fullName is baseName.extension. */
|
||||
|
||||
class StorageDelegate;
|
||||
|
||||
class InternalStorage {
|
||||
public:
|
||||
typedef uint16_t record_size_t;
|
||||
|
||||
static constexpr char eqExtension[] = "eq";
|
||||
static constexpr char expExtension[] = "exp";
|
||||
static constexpr char funcExtension[] = "func";
|
||||
static constexpr char seqExtension[] = "seq";
|
||||
|
||||
constexpr static size_t k_storageSize = 60000;
|
||||
static_assert(UINT16_MAX >= k_storageSize, "record_size_t not big enough");
|
||||
|
||||
constexpr static char k_dotChar = '.';
|
||||
|
||||
class Record {
|
||||
/* A Record is identified by the CRC32 on its fullName because:
|
||||
* - A record is identified by its fullName, which is unique
|
||||
* - We cannot keep the address pointing to the fullName because if another
|
||||
* record is modified, it might alter our record's fullName address.
|
||||
* Keeping a buffer with the fullNames will waste memory as we cannot
|
||||
* forsee the size of the fullNames. */
|
||||
friend class Storage;
|
||||
public:
|
||||
enum class ErrorStatus {
|
||||
None = 0,
|
||||
NameTaken = 1,
|
||||
NonCompliantName = 2,
|
||||
NotEnoughSpaceAvailable = 3,
|
||||
RecordDoesNotExist = 4
|
||||
};
|
||||
struct Data {
|
||||
const void * buffer;
|
||||
size_t size;
|
||||
};
|
||||
Record(const char * fullName = nullptr);
|
||||
Record(const char * basename, const char * extension);
|
||||
bool operator==(const Record & other) const {
|
||||
return m_fullNameCRC32 == other.m_fullNameCRC32;
|
||||
}
|
||||
bool operator!=(const Record & other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
#if ION_STORAGE_LOG
|
||||
void log();
|
||||
#endif
|
||||
uint32_t checksum();
|
||||
bool isNull() const {
|
||||
return m_fullNameCRC32 == 0;
|
||||
}
|
||||
const char * fullName() const;
|
||||
ErrorStatus setBaseNameWithExtension(const char * baseName, const char * extension);
|
||||
ErrorStatus setName(const char * fullName);
|
||||
Data value() const;
|
||||
ErrorStatus setValue(Data data);
|
||||
void destroy();
|
||||
private:
|
||||
Record(const char * basename, int basenameLength, const char * extension, int extensionLength);
|
||||
uint32_t m_fullNameCRC32;
|
||||
};
|
||||
|
||||
#if ION_STORAGE_LOG
|
||||
void log();
|
||||
#endif
|
||||
|
||||
size_t availableSize();
|
||||
size_t putAvailableSpaceAtEndOfRecord(Record r);
|
||||
void getAvailableSpaceFromEndOfRecord(Record r, size_t recordAvailableSpace);
|
||||
uint32_t checksum();
|
||||
|
||||
// Delegate
|
||||
void setDelegate(StorageDelegate * delegate) { m_delegate = delegate; }
|
||||
void notifyChangeToDelegate(const Record r = Record()) const;
|
||||
Record::ErrorStatus notifyFullnessToDelegate() const;
|
||||
|
||||
int numberOfRecordsWithExtension(const char * extension);
|
||||
static bool FullNameHasExtension(const char * fullName, const char * extension, size_t extensionLength);
|
||||
|
||||
// Record creation
|
||||
Record::ErrorStatus createRecordWithFullName(const char * fullName, const void * data, size_t size);
|
||||
Record::ErrorStatus createRecordWithExtension(const char * baseName, const char * extension, const void * data, size_t size);
|
||||
|
||||
// Record getters
|
||||
bool hasRecord(Record r) { return pointerOfRecord(r) != nullptr; }
|
||||
Record recordWithExtensionAtIndex(const char * extension, int index);
|
||||
Record recordNamed(const char * fullName);
|
||||
Record recordBaseNamedWithExtension(const char * baseName, const char * extension);
|
||||
Record recordBaseNamedWithExtensions(const char * baseName, const char * const extension[], size_t numberOfExtensions);
|
||||
const char * extensionOfRecordBaseNamedWithExtensions(const char * baseName, int baseNameLength, const char * const extension[], size_t numberOfExtensions);
|
||||
|
||||
// Record destruction
|
||||
void destroyAllRecords();
|
||||
void destroyRecordWithBaseNameAndExtension(const char * baseName, const char * extension);
|
||||
void destroyRecordsWithExtension(const char * extension);
|
||||
|
||||
// Useful
|
||||
static bool FullNameCompliant(const char * name);
|
||||
|
||||
// Used by Python OS module
|
||||
int numberOfRecords();
|
||||
Record recordAtIndex(int index);
|
||||
protected:
|
||||
InternalStorage();
|
||||
/* Getters on address in buffer */
|
||||
char * pointerOfRecord(const Record record) const;
|
||||
record_size_t sizeOfRecordStarting(char * start) const;
|
||||
const char * fullNameOfRecordStarting(char * start) const;
|
||||
const void * valueOfRecordStarting(char * start) const;
|
||||
void destroyRecord(const Record record);
|
||||
|
||||
class RecordIterator {
|
||||
public:
|
||||
RecordIterator(char * start) : m_recordStart(start) {}
|
||||
char * operator*() { return m_recordStart; }
|
||||
RecordIterator& operator++();
|
||||
bool operator!=(const RecordIterator& it) const { return m_recordStart != it.m_recordStart; }
|
||||
private:
|
||||
char * m_recordStart;
|
||||
};
|
||||
RecordIterator begin() const {
|
||||
if (sizeOfRecordStarting((char *)m_buffer) == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
return RecordIterator((char *)m_buffer);
|
||||
};
|
||||
RecordIterator end() const { return RecordIterator(nullptr); }
|
||||
|
||||
mutable Record m_lastRecordRetrieved;
|
||||
mutable char * m_lastRecordRetrievedPointer;
|
||||
private:
|
||||
constexpr static uint32_t Magic = 0xEE0BDDBA;
|
||||
constexpr static size_t k_maxRecordSize = (1 << sizeof(record_size_t)*8);
|
||||
|
||||
/* Getters/Setters on recordID */
|
||||
const char * fullNameOfRecord(const Record record);
|
||||
Record::ErrorStatus setFullNameOfRecord(const Record record, const char * fullName);
|
||||
Record::ErrorStatus setBaseNameWithExtensionOfRecord(const Record record, const char * baseName, const char * extension);
|
||||
Record::Data valueOfRecord(const Record record);
|
||||
Record::ErrorStatus setValueOfRecord(const Record record, Record::Data data);
|
||||
|
||||
/* Overriders */
|
||||
size_t overrideSizeAtPosition(char * position, record_size_t size);
|
||||
size_t overrideFullNameAtPosition(char * position, const char * fullName);
|
||||
size_t overrideBaseNameWithExtensionAtPosition(char * position, const char * baseName, const char * extension);
|
||||
size_t overrideValueAtPosition(char * position, const void * data, record_size_t size);
|
||||
|
||||
bool isFullNameTaken(const char * fullName, const Record * recordToExclude = nullptr);
|
||||
bool isBaseNameWithExtensionTaken(const char * baseName, const char * extension, Record * recordToExclude = nullptr);
|
||||
bool isNameOfRecordTaken(Record r, const Record * recordToExclude);
|
||||
char * endBuffer();
|
||||
size_t sizeOfBaseNameAndExtension(const char * baseName, const char * extension) const;
|
||||
size_t sizeOfRecordWithBaseNameAndExtension(const char * baseName, const char * extension, size_t size) const;
|
||||
size_t sizeOfRecordWithFullName(const char * fullName, size_t size) const;
|
||||
bool slideBuffer(char * position, int delta);
|
||||
|
||||
Record privateRecordAndExtensionOfRecordBaseNamedWithExtensions(const char * baseName, const char * const extensions[], size_t numberOfExtensions, const char * * extensionResult = nullptr, int baseNameLength = -1);
|
||||
|
||||
uint32_t m_magicHeader;
|
||||
char m_buffer[k_storageSize];
|
||||
uint32_t m_magicFooter;
|
||||
StorageDelegate * m_delegate;
|
||||
};
|
||||
|
||||
/* Some apps memoize records and need to be notified when a record might have
|
||||
* become invalid. For instance in the Graph app, if f(x) = A+x, and A changed,
|
||||
* f(x) memoization which stores the reduced expression of f is outdated.
|
||||
* We could have computed and compared the checksum of the storage to detect
|
||||
* storage invalidity, but profiling showed that this slows down the execution
|
||||
* (for example when scrolling the functions list).
|
||||
* We thus decided to notify a delegate when the storage changes. */
|
||||
|
||||
class StorageDelegate {
|
||||
public:
|
||||
virtual void storageDidChangeForRecord(const InternalStorage::Record record) = 0;
|
||||
virtual void storageIsFull() = 0;
|
||||
};
|
||||
|
||||
// emscripten read and writes must be aligned.
|
||||
class StorageHelper {
|
||||
public:
|
||||
static uint16_t unalignedShort(char * address) {
|
||||
#if __EMSCRIPTEN__
|
||||
uint8_t f1 = *(address);
|
||||
uint8_t f2 = *(address+1);
|
||||
uint16_t f = (uint16_t)f1 + (((uint16_t)f2)<<8);
|
||||
return f;
|
||||
#else
|
||||
return *(uint16_t *)address;
|
||||
#endif
|
||||
}
|
||||
static void writeUnalignedShort(uint16_t value, char * address) {
|
||||
#if __EMSCRIPTEN__
|
||||
*((uint8_t *)address) = (uint8_t)(value & ((1 << 8) - 1));
|
||||
*((uint8_t *)address+1) = (uint8_t)(value >> 8);
|
||||
#else
|
||||
*((uint16_t *)address) = value;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,239 +1,50 @@
|
||||
#ifndef ION_STORAGE_H
|
||||
#define ION_STORAGE_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "internal_storage.h"
|
||||
|
||||
namespace Ion {
|
||||
|
||||
/* Storage : | Magic | Record1 | Record2 | ... | Magic |
|
||||
* | Magic | Size1(uint16_t) | FullName1 | Body1 | Size2(uint16_t) | FullName2 | Body2 | ... | Magic |
|
||||
*
|
||||
* A record's fullName is baseName.extension. */
|
||||
|
||||
class StorageDelegate;
|
||||
|
||||
class Storage {
|
||||
class Storage : public InternalStorage {
|
||||
public:
|
||||
typedef uint16_t record_size_t;
|
||||
using InternalStorage::Record;
|
||||
|
||||
constexpr static size_t k_storageSize = 60000;
|
||||
static_assert(UINT16_MAX >= k_storageSize, "record_size_t not big enough");
|
||||
using InternalStorage::expExtension;
|
||||
using InternalStorage::funcExtension;
|
||||
using InternalStorage::seqExtension;
|
||||
using InternalStorage::eqExtension;
|
||||
|
||||
static Storage * sharedStorage();
|
||||
constexpr static char k_dotChar = '.';
|
||||
|
||||
static constexpr char eqExtension[] = "eq";
|
||||
static constexpr char expExtension[] = "exp";
|
||||
static constexpr char funcExtension[] = "func";
|
||||
static constexpr char seqExtension[] = "seq";
|
||||
|
||||
class Record {
|
||||
/* A Record is identified by the CRC32 on its fullName because:
|
||||
* - A record is identified by its fullName, which is unique
|
||||
* - We cannot keep the address pointing to the fullName because if another
|
||||
* record is modified, it might alter our record's fullName address.
|
||||
* Keeping a buffer with the fullNames will waste memory as we cannot
|
||||
* forsee the size of the fullNames. */
|
||||
friend class Storage;
|
||||
public:
|
||||
enum class ErrorStatus {
|
||||
None = 0,
|
||||
NameTaken = 1,
|
||||
NonCompliantName = 2,
|
||||
NotEnoughSpaceAvailable = 3,
|
||||
RecordDoesNotExist = 4
|
||||
};
|
||||
struct Data {
|
||||
const void * buffer;
|
||||
size_t size;
|
||||
};
|
||||
Record(const char * fullName = nullptr);
|
||||
Record(const char * basename, const char * extension);
|
||||
bool operator==(const Record & other) const {
|
||||
return m_fullNameCRC32 == other.m_fullNameCRC32;
|
||||
}
|
||||
bool operator!=(const Record & other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
#if ION_STORAGE_LOG
|
||||
void log();
|
||||
#endif
|
||||
uint32_t checksum();
|
||||
bool isNull() const {
|
||||
return m_fullNameCRC32 == 0;
|
||||
}
|
||||
const char * fullName() const {
|
||||
return Storage::sharedStorage()->fullNameOfRecord(*this);
|
||||
}
|
||||
ErrorStatus setBaseNameWithExtension(const char * baseName, const char * extension) {
|
||||
return Storage::sharedStorage()->setBaseNameWithExtensionOfRecord(*this, baseName, extension);
|
||||
}
|
||||
ErrorStatus setName(const char * fullName) {
|
||||
return Storage::sharedStorage()->setFullNameOfRecord(*this, fullName);
|
||||
}
|
||||
Data value() const {
|
||||
return Storage::sharedStorage()->valueOfRecord(*this);
|
||||
}
|
||||
ErrorStatus setValue(Data data) {
|
||||
return Storage::sharedStorage()->setValueOfRecord(*this, data);
|
||||
}
|
||||
void destroy() {
|
||||
return Storage::sharedStorage()->destroyRecord(*this);
|
||||
}
|
||||
private:
|
||||
Record(const char * basename, int basenameLength, const char * extension, int extensionLength);
|
||||
uint32_t m_fullNameCRC32;
|
||||
};
|
||||
|
||||
#if ION_STORAGE_LOG
|
||||
void log();
|
||||
#endif
|
||||
|
||||
size_t availableSize();
|
||||
size_t putAvailableSpaceAtEndOfRecord(Record r);
|
||||
void getAvailableSpaceFromEndOfRecord(Record r, size_t recordAvailableSpace);
|
||||
uint32_t checksum();
|
||||
|
||||
// Delegate
|
||||
void setDelegate(StorageDelegate * delegate) { m_delegate = delegate; }
|
||||
void notifyChangeToDelegate(const Record r = Record()) const;
|
||||
Record::ErrorStatus notifyFullnessToDelegate() const;
|
||||
|
||||
int numberOfRecordsWithExtension(const char * extension);
|
||||
static bool FullNameHasExtension(const char * fullName, const char * extension, size_t extensionLength);
|
||||
|
||||
// Record creation
|
||||
Record::ErrorStatus createRecordWithFullName(const char * fullName, const void * data, size_t size);
|
||||
Record::ErrorStatus createRecordWithExtension(const char * baseName, const char * extension, const void * data, size_t size);
|
||||
|
||||
// Record getters
|
||||
bool hasRecord(Record r) { return pointerOfRecord(r) != nullptr; }
|
||||
bool hasRecord(Record r);
|
||||
|
||||
Record recordWithExtensionAtIndex(const char * extension, int index);
|
||||
Record recordNamed(const char * fullName);
|
||||
Record recordBaseNamedWithExtension(const char * baseName, const char * extension);
|
||||
Record recordBaseNamedWithExtensions(const char * baseName, const char * const extension[], size_t numberOfExtensions);
|
||||
const char * extensionOfRecordBaseNamedWithExtensions(const char * baseName, int baseNameLength, const char * const extension[], size_t numberOfExtensions);
|
||||
|
||||
// Record destruction
|
||||
void destroyAllRecords();
|
||||
void destroyRecordWithBaseNameAndExtension(const char * baseName, const char * extension);
|
||||
void destroyRecordsWithExtension(const char * extension);
|
||||
|
||||
// Useful
|
||||
static bool FullNameCompliant(const char * name);
|
||||
|
||||
// Used by Python OS module
|
||||
int numberOfRecords();
|
||||
Record recordAtIndex(int index); // Unlike realRecordAtIndex, this ignore trash
|
||||
Record recordAtIndex(int index);
|
||||
void destroyRecord(Record record);
|
||||
|
||||
// Trash
|
||||
void reinsertTrash(const char * extension);
|
||||
void emptyTrash();
|
||||
|
||||
private:
|
||||
constexpr static uint32_t Magic = 0xEE0BDDBA;
|
||||
constexpr static size_t k_maxRecordSize = (1 << sizeof(record_size_t)*8);
|
||||
Storage():
|
||||
InternalStorage() {}
|
||||
|
||||
Storage();
|
||||
|
||||
/* Getters/Setters on recordID */
|
||||
const char * fullNameOfRecord(const Record record);
|
||||
Record::ErrorStatus setFullNameOfRecord(const Record record, const char * fullName);
|
||||
Record::ErrorStatus setBaseNameWithExtensionOfRecord(const Record record, const char * baseName, const char * extension);
|
||||
Record::Data valueOfRecord(const Record record);
|
||||
Record::ErrorStatus setValueOfRecord(const Record record, Record::Data data);
|
||||
void destroyRecord(const Record record);
|
||||
void realDestroyRecord(const Record record);
|
||||
|
||||
/* Getters on address in buffer */
|
||||
char * pointerOfRecord(const Record record) const;
|
||||
record_size_t sizeOfRecordStarting(char * start) const;
|
||||
const char * fullNameOfRecordStarting(char * start) const;
|
||||
const void * valueOfRecordStarting(char * start) const;
|
||||
|
||||
/* Trash */
|
||||
void emptyTrash();
|
||||
Storage::Record realRecordAtIndex(int index);
|
||||
int realNumberOfRecords();
|
||||
|
||||
/* Overriders */
|
||||
size_t overrideSizeAtPosition(char * position, record_size_t size);
|
||||
size_t overrideFullNameAtPosition(char * position, const char * fullName);
|
||||
size_t overrideBaseNameWithExtensionAtPosition(char * position, const char * baseName, const char * extension);
|
||||
size_t overrideValueAtPosition(char * position, const void * data, record_size_t size);
|
||||
|
||||
size_t realAvailableSize();
|
||||
bool isFullNameTaken(const char * fullName, const Record * recordToExclude = nullptr);
|
||||
bool isBaseNameWithExtensionTaken(const char * baseName, const char * extension, Record * recordToExclude = nullptr);
|
||||
bool isNameOfRecordTaken(Record r, const Record * recordToExclude);
|
||||
char * endBuffer();
|
||||
size_t sizeOfBaseNameAndExtension(const char * baseName, const char * extension) const;
|
||||
size_t sizeOfRecordWithBaseNameAndExtension(const char * baseName, const char * extension, size_t size) const;
|
||||
size_t sizeOfRecordWithFullName(const char * fullName, size_t size) const;
|
||||
bool slideBuffer(char * position, int delta);
|
||||
class RecordIterator {
|
||||
public:
|
||||
RecordIterator(char * start) : m_recordStart(start) {}
|
||||
char * operator*() { return m_recordStart; }
|
||||
RecordIterator& operator++();
|
||||
bool operator!=(const RecordIterator& it) const { return m_recordStart != it.m_recordStart; }
|
||||
private:
|
||||
char * m_recordStart;
|
||||
};
|
||||
RecordIterator begin() const {
|
||||
if (sizeOfRecordStarting((char *)m_buffer) == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
return RecordIterator((char *)m_buffer);
|
||||
};
|
||||
RecordIterator end() const { return RecordIterator(nullptr); }
|
||||
|
||||
Record privateRecordAndExtensionOfRecordBaseNamedWithExtensions(const char * baseName, const char * const extensions[], size_t numberOfExtensions, const char * * extensionResult = nullptr, int baseNameLength = -1);
|
||||
|
||||
uint32_t m_magicHeader;
|
||||
char m_buffer[k_storageSize];
|
||||
Record m_trashRecord;
|
||||
uint32_t m_magicFooter;
|
||||
StorageDelegate * m_delegate;
|
||||
mutable Record m_lastRecordRetrieved;
|
||||
mutable char * m_lastRecordRetrievedPointer;
|
||||
};
|
||||
|
||||
/* Some apps memoize records and need to be notified when a record might have
|
||||
* become invalid. For instance in the Graph app, if f(x) = A+x, and A changed,
|
||||
* f(x) memoization which stores the reduced expression of f is outdated.
|
||||
* We could have computed and compared the checksum of the storage to detect
|
||||
* storage invalidity, but profiling showed that this slows down the execution
|
||||
* (for example when scrolling the functions list).
|
||||
* We thus decided to notify a delegate when the storage changes. */
|
||||
|
||||
class StorageDelegate {
|
||||
public:
|
||||
virtual void storageDidChangeForRecord(const Storage::Record record) = 0;
|
||||
virtual void storageIsFull() = 0;
|
||||
};
|
||||
|
||||
// emscripten read and writes must be aligned.
|
||||
class StorageHelper {
|
||||
public:
|
||||
static uint16_t unalignedShort(char * address) {
|
||||
#if __EMSCRIPTEN__
|
||||
uint8_t f1 = *(address);
|
||||
uint8_t f2 = *(address+1);
|
||||
uint16_t f = (uint16_t)f1 + (((uint16_t)f2)<<8);
|
||||
return f;
|
||||
#else
|
||||
return *(uint16_t *)address;
|
||||
#endif
|
||||
}
|
||||
static void writeUnalignedShort(uint16_t value, char * address) {
|
||||
#if __EMSCRIPTEN__
|
||||
*((uint8_t *)address) = (uint8_t)(value & ((1 << 8) - 1));
|
||||
*((uint8_t *)address+1) = (uint8_t)(value >> 8);
|
||||
#else
|
||||
*((uint16_t *)address) = value;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -236,6 +236,8 @@ SECTIONS {
|
||||
. = ALIGN(4);
|
||||
*(.rodata._ZN3Ion6Device13ExternalFlash*)
|
||||
/* 'start' dependencies */
|
||||
*(.rodata._ZN3Ion6Device8Keyboard6ConfigL10ColumnGPIOE*)
|
||||
*(.rodata._ZN3Ion6Device8Keyboard6ConfigL7RowGPIOE*)
|
||||
*(.rodata._ZN3Ion6Device4RegsL5GPIOAE)
|
||||
*(.rodata._ZN3Ion6Device4RegsL5GPIOBE)
|
||||
*(.rodata._ZN3Ion6Device3LED6ConfigL7RGBPinsE)
|
||||
|
||||
647
ion/src/shared/internal_storage.cpp
Normal file
647
ion/src/shared/internal_storage.cpp
Normal file
@@ -0,0 +1,647 @@
|
||||
#include <ion.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <new>
|
||||
#include <ion/internal_storage.h>
|
||||
#if ION_STORAGE_LOG
|
||||
#include <iostream>
|
||||
#endif
|
||||
|
||||
namespace Ion {
|
||||
|
||||
/* We want to implement a simple singleton pattern, to make sure the storage is
|
||||
* initialized on first use, therefore preventing the static init order fiasco.
|
||||
* That being said, we rely on knowing where the storage resides in the device's
|
||||
* memory at compile time. Indeed, we want to advertise the static storage's
|
||||
* memory address in the PlatformInfo structure (so that we can read and write
|
||||
* it in DFU).
|
||||
* Using a "static Storage storage;" variable makes it a local symbol at best,
|
||||
* preventing the PlatformInfo from retrieving its address. And making the
|
||||
* Storage variable global yields the static init fiasco issue. We're working
|
||||
* around both issues by creating a global staticStorageArea buffer, and by
|
||||
* placement-newing the Storage into that area on first use. */
|
||||
|
||||
/* The InternalStorage is handle all records. Then the "normal" Storage handle
|
||||
* a trash */
|
||||
|
||||
constexpr char InternalStorage::expExtension[];
|
||||
constexpr char InternalStorage::funcExtension[];
|
||||
constexpr char InternalStorage::seqExtension[];
|
||||
constexpr char InternalStorage::eqExtension[];
|
||||
|
||||
// RECORD
|
||||
|
||||
const char * InternalStorage::Record::fullName() const {
|
||||
return Storage::sharedStorage()->fullNameOfRecord(*this);
|
||||
}
|
||||
InternalStorage::Record::ErrorStatus InternalStorage::Record::setBaseNameWithExtension(const char * baseName, const char * extension) {
|
||||
return Storage::sharedStorage()->setBaseNameWithExtensionOfRecord(*this, baseName, extension);
|
||||
}
|
||||
InternalStorage::Record::ErrorStatus InternalStorage::Record::setName(const char * fullName) {
|
||||
return Storage::sharedStorage()->setFullNameOfRecord(*this, fullName);
|
||||
}
|
||||
InternalStorage::Record::Data InternalStorage::Record::value() const {
|
||||
return Storage::sharedStorage()->valueOfRecord(*this);
|
||||
}
|
||||
InternalStorage::Record::ErrorStatus InternalStorage::Record::setValue(Data data) {
|
||||
return Storage::sharedStorage()->setValueOfRecord(*this, data);
|
||||
}
|
||||
void InternalStorage::Record::destroy() {
|
||||
return Storage::sharedStorage()->destroyRecord(*this);
|
||||
}
|
||||
|
||||
InternalStorage::Record::Record(const char * fullName) {
|
||||
if (fullName == nullptr) {
|
||||
m_fullNameCRC32 = 0;
|
||||
return;
|
||||
}
|
||||
const char * dotChar = UTF8Helper::CodePointSearch(fullName, k_dotChar);
|
||||
// If no extension, return empty record
|
||||
if (*dotChar == 0 || *(dotChar+1) == 0) {
|
||||
m_fullNameCRC32 = 0;
|
||||
return;
|
||||
}
|
||||
new (this) Record(fullName, dotChar - fullName, dotChar+1, (fullName + strlen(fullName)) - (dotChar+1));
|
||||
}
|
||||
|
||||
InternalStorage::Record::Record(const char * baseName, const char * extension) {
|
||||
if (baseName == nullptr) {
|
||||
assert(extension == nullptr);
|
||||
m_fullNameCRC32 = 0;
|
||||
return;
|
||||
}
|
||||
new (this) Record(baseName, strlen(baseName), extension, strlen(extension));
|
||||
}
|
||||
|
||||
|
||||
#if ION_STORAGE_LOG
|
||||
|
||||
void InternalStorage::Record::log() {
|
||||
std::cout << "Name: " << fullName() << std::endl;
|
||||
std::cout << " Value (" << value().size << "): " << (char *)value().buffer << "\n\n" << std::endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32_t InternalStorage::Record::checksum() {
|
||||
uint32_t crc32Results[2];
|
||||
crc32Results[0] = m_fullNameCRC32;
|
||||
Data data = value();
|
||||
crc32Results[1] = Ion::crc32Byte((const uint8_t *)data.buffer, data.size);
|
||||
return Ion::crc32Word(crc32Results, 2);
|
||||
}
|
||||
|
||||
InternalStorage::Record::Record(const char * basename, int basenameLength, const char * extension, int extensionLength) {
|
||||
assert(basename != nullptr);
|
||||
assert(extension != nullptr);
|
||||
|
||||
// We compute the CRC32 of the CRC32s of the basename and the extension
|
||||
uint32_t crc32Results[2];
|
||||
crc32Results[0] = Ion::crc32Byte((const uint8_t *)basename, basenameLength);
|
||||
crc32Results[1] = Ion::crc32Byte((const uint8_t *)extension, extensionLength);
|
||||
m_fullNameCRC32 = Ion::crc32Word(crc32Results, 2);
|
||||
}
|
||||
|
||||
// STORAGE
|
||||
|
||||
#if ION_STORAGE_LOG
|
||||
void InternalStorage::log() {
|
||||
for (char * p : *this) {
|
||||
const char * currentName = fullNameOfRecordStarting(p);
|
||||
Record(currentName).log();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t InternalStorage::availableSize() {
|
||||
/* TODO maybe do: availableSize(char ** endBuffer) to get the endBuffer if it
|
||||
* is needed after calling availableSize */
|
||||
assert(k_storageSize >= (endBuffer() - m_buffer) + sizeof(record_size_t));
|
||||
return k_storageSize-(endBuffer()-m_buffer)-sizeof(record_size_t);
|
||||
}
|
||||
|
||||
size_t InternalStorage::putAvailableSpaceAtEndOfRecord(InternalStorage::Record r) {
|
||||
char * p = pointerOfRecord(r);
|
||||
size_t previousRecordSize = sizeOfRecordStarting(p);
|
||||
size_t availableStorageSize = availableSize();
|
||||
char * nextRecord = p + previousRecordSize;
|
||||
memmove(nextRecord + availableStorageSize,
|
||||
nextRecord,
|
||||
(m_buffer + k_storageSize - availableStorageSize) - nextRecord);
|
||||
size_t newRecordSize = previousRecordSize + availableStorageSize;
|
||||
overrideSizeAtPosition(p, (record_size_t)newRecordSize);
|
||||
return newRecordSize;
|
||||
}
|
||||
|
||||
void InternalStorage::getAvailableSpaceFromEndOfRecord(Record r, size_t recordAvailableSpace) {
|
||||
char * p = pointerOfRecord(r);
|
||||
size_t previousRecordSize = sizeOfRecordStarting(p);
|
||||
char * nextRecord = p + previousRecordSize;
|
||||
memmove(nextRecord - recordAvailableSpace,
|
||||
nextRecord,
|
||||
m_buffer + k_storageSize - nextRecord);
|
||||
overrideSizeAtPosition(p, (record_size_t)(previousRecordSize - recordAvailableSpace));
|
||||
}
|
||||
|
||||
uint32_t InternalStorage::checksum() {
|
||||
return Ion::crc32Byte((const uint8_t *) m_buffer, endBuffer()-m_buffer);
|
||||
}
|
||||
|
||||
void InternalStorage::notifyChangeToDelegate(const Record record) const {
|
||||
m_lastRecordRetrieved = Record(nullptr);
|
||||
m_lastRecordRetrievedPointer = nullptr;
|
||||
if (m_delegate != nullptr) {
|
||||
m_delegate->storageDidChangeForRecord(record);
|
||||
}
|
||||
}
|
||||
|
||||
InternalStorage::Record::ErrorStatus InternalStorage::notifyFullnessToDelegate() const {
|
||||
if (m_delegate != nullptr) {
|
||||
m_delegate->storageIsFull();
|
||||
}
|
||||
return Record::ErrorStatus::NotEnoughSpaceAvailable;
|
||||
}
|
||||
|
||||
InternalStorage::Record::ErrorStatus InternalStorage::createRecordWithFullName(const char * fullName, const void * data, size_t size) {
|
||||
size_t recordSize = sizeOfRecordWithFullName(fullName, size);
|
||||
if (recordSize >= k_maxRecordSize || recordSize > availableSize()) {
|
||||
return notifyFullnessToDelegate();
|
||||
}
|
||||
if (isFullNameTaken(fullName)) {
|
||||
return Record::ErrorStatus::NameTaken;
|
||||
}
|
||||
// Find the end of data
|
||||
char * newRecordAddress = endBuffer();
|
||||
char * newRecord = newRecordAddress;
|
||||
// Fill totalSize
|
||||
newRecord += overrideSizeAtPosition(newRecord, (record_size_t)recordSize);
|
||||
// Fill name
|
||||
newRecord += overrideFullNameAtPosition(newRecord, fullName);
|
||||
// Fill data
|
||||
newRecord += overrideValueAtPosition(newRecord, data, size);
|
||||
// Next Record is null-sized
|
||||
overrideSizeAtPosition(newRecord, 0);
|
||||
Record r = Record(fullName);
|
||||
notifyChangeToDelegate(r);
|
||||
m_lastRecordRetrieved = r;
|
||||
m_lastRecordRetrievedPointer = newRecordAddress;
|
||||
return Record::ErrorStatus::None;
|
||||
}
|
||||
|
||||
InternalStorage::Record::ErrorStatus InternalStorage::createRecordWithExtension(const char * baseName, const char * extension, const void * data, size_t size) {
|
||||
size_t recordSize = sizeOfRecordWithBaseNameAndExtension(baseName, extension, size);
|
||||
if (recordSize >= k_maxRecordSize || recordSize > availableSize()) {
|
||||
return notifyFullnessToDelegate();
|
||||
}
|
||||
if (isBaseNameWithExtensionTaken(baseName, extension)) {
|
||||
return Record::ErrorStatus::NameTaken;
|
||||
}
|
||||
// Find the end of data
|
||||
char * newRecordAddress = endBuffer();
|
||||
char * newRecord = newRecordAddress;
|
||||
// Fill totalSize
|
||||
newRecord += overrideSizeAtPosition(newRecord, (record_size_t)recordSize);
|
||||
// Fill name
|
||||
newRecord += overrideBaseNameWithExtensionAtPosition(newRecord, baseName, extension);
|
||||
// Fill data
|
||||
newRecord += overrideValueAtPosition(newRecord, data, size);
|
||||
// Next Record is null-sized
|
||||
overrideSizeAtPosition(newRecord, 0);
|
||||
Record r = Record(fullNameOfRecordStarting(newRecordAddress));
|
||||
notifyChangeToDelegate(r);
|
||||
m_lastRecordRetrieved = r;
|
||||
m_lastRecordRetrievedPointer = newRecordAddress;
|
||||
return Record::ErrorStatus::None;
|
||||
}
|
||||
|
||||
int InternalStorage::numberOfRecordsWithExtension(const char * extension) {
|
||||
int count = 0;
|
||||
size_t extensionLength = strlen(extension);
|
||||
for (char * p : *this) {
|
||||
const char * name = fullNameOfRecordStarting(p);
|
||||
if (FullNameHasExtension(name, extension, extensionLength)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int InternalStorage::numberOfRecords() {
|
||||
int count = 0;
|
||||
for (char * p : *this) {
|
||||
const char * name = fullNameOfRecordStarting(p);
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
InternalStorage::Record InternalStorage::recordAtIndex(int index) {
|
||||
int currentIndex = -1;
|
||||
const char * name = nullptr;
|
||||
char * recordAddress = nullptr;
|
||||
for (char * p : *this) {
|
||||
const char * currentName = fullNameOfRecordStarting(p);
|
||||
currentIndex++;
|
||||
if (currentIndex == index) {
|
||||
recordAddress = p;
|
||||
name = currentName;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (name == nullptr) {
|
||||
return Record();
|
||||
}
|
||||
Record r = Record(name);
|
||||
m_lastRecordRetrieved = r;
|
||||
m_lastRecordRetrievedPointer = recordAddress;
|
||||
return Record(name);
|
||||
}
|
||||
|
||||
InternalStorage::Record InternalStorage::recordWithExtensionAtIndex(const char * extension, int index) {
|
||||
int currentIndex = -1;
|
||||
const char * name = nullptr;
|
||||
size_t extensionLength = strlen(extension);
|
||||
char * recordAddress = nullptr;
|
||||
for (char * p : *this) {
|
||||
const char * currentName = fullNameOfRecordStarting(p);
|
||||
if (FullNameHasExtension(currentName, extension, extensionLength)) {
|
||||
currentIndex++;
|
||||
}
|
||||
if (currentIndex == index) {
|
||||
recordAddress = p;
|
||||
name = currentName;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (name == nullptr) {
|
||||
return Record();
|
||||
}
|
||||
Record r = Record(name);
|
||||
m_lastRecordRetrieved = r;
|
||||
m_lastRecordRetrievedPointer = recordAddress;
|
||||
return Record(name);
|
||||
}
|
||||
|
||||
InternalStorage::Record InternalStorage::recordNamed(const char * fullName) {
|
||||
if (fullName == nullptr) {
|
||||
return Record();
|
||||
}
|
||||
Record r = Record(fullName);
|
||||
char * p = pointerOfRecord(r);
|
||||
if (p != nullptr) {
|
||||
return r;
|
||||
}
|
||||
return Record();
|
||||
}
|
||||
|
||||
InternalStorage::Record InternalStorage::recordBaseNamedWithExtension(const char * baseName, const char * extension) {
|
||||
const char * extensions[1] = {extension};
|
||||
return recordBaseNamedWithExtensions(baseName, extensions, 1);
|
||||
}
|
||||
|
||||
InternalStorage::Record InternalStorage::recordBaseNamedWithExtensions(const char * baseName, const char * const extensions[], size_t numberOfExtensions) {
|
||||
return privateRecordAndExtensionOfRecordBaseNamedWithExtensions(baseName, extensions, numberOfExtensions);
|
||||
}
|
||||
|
||||
const char * InternalStorage::extensionOfRecordBaseNamedWithExtensions(const char * baseName, int baseNameLength, const char * const extensions[], size_t numberOfExtensions) {
|
||||
const char * result = nullptr;
|
||||
privateRecordAndExtensionOfRecordBaseNamedWithExtensions(baseName, extensions, numberOfExtensions, &result, baseNameLength);
|
||||
return result;
|
||||
}
|
||||
|
||||
void InternalStorage::destroyAllRecords() {
|
||||
overrideSizeAtPosition(m_buffer, 0);
|
||||
notifyChangeToDelegate();
|
||||
}
|
||||
|
||||
void InternalStorage::destroyRecordWithBaseNameAndExtension(const char * baseName, const char * extension) {
|
||||
recordBaseNamedWithExtension(baseName, extension).destroy();
|
||||
}
|
||||
|
||||
void InternalStorage::destroyRecordsWithExtension(const char * extension) {
|
||||
size_t extensionLength = strlen(extension);
|
||||
char * currentRecordStart = (char *)m_buffer;
|
||||
bool didChange = false;
|
||||
while (currentRecordStart != nullptr && sizeOfRecordStarting(currentRecordStart) != 0) {
|
||||
const char * currentFullName = fullNameOfRecordStarting(currentRecordStart);
|
||||
if (FullNameHasExtension(currentFullName, extension, extensionLength)) {
|
||||
Record currentRecord(currentFullName);
|
||||
currentRecord.destroy();
|
||||
didChange = true;
|
||||
continue;
|
||||
}
|
||||
currentRecordStart = *(RecordIterator(currentRecordStart).operator++());
|
||||
}
|
||||
if (didChange) {
|
||||
notifyChangeToDelegate();
|
||||
}
|
||||
}
|
||||
|
||||
InternalStorage::InternalStorage() :
|
||||
m_magicHeader(Magic),
|
||||
m_buffer(),
|
||||
m_magicFooter(Magic),
|
||||
m_delegate(nullptr),
|
||||
m_lastRecordRetrieved(nullptr),
|
||||
m_lastRecordRetrievedPointer(nullptr)
|
||||
{
|
||||
assert(m_magicHeader == Magic);
|
||||
assert(m_magicFooter == Magic);
|
||||
// Set the size of the first record to 0
|
||||
overrideSizeAtPosition(m_buffer, 0);
|
||||
}
|
||||
|
||||
// PRIVATE
|
||||
|
||||
const char * InternalStorage::fullNameOfRecord(const Record record) {
|
||||
char * p = pointerOfRecord(record);
|
||||
if (p != nullptr) {
|
||||
return fullNameOfRecordStarting(p);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
InternalStorage::Record::ErrorStatus InternalStorage::setFullNameOfRecord(const Record record, const char * fullName) {
|
||||
if (!FullNameCompliant(fullName)) {
|
||||
return Record::ErrorStatus::NonCompliantName;
|
||||
}
|
||||
if (isFullNameTaken(fullName, &record)) {
|
||||
return Record::ErrorStatus::NameTaken;
|
||||
}
|
||||
size_t nameSize = strlen(fullName) + 1;
|
||||
char * p = pointerOfRecord(record);
|
||||
if (p != nullptr) {
|
||||
size_t previousNameSize = strlen(fullNameOfRecordStarting(p))+1;
|
||||
record_size_t previousRecordSize = sizeOfRecordStarting(p);
|
||||
size_t newRecordSize = previousRecordSize-previousNameSize+nameSize;
|
||||
if (newRecordSize >= k_maxRecordSize || !slideBuffer(p+sizeof(record_size_t)+previousNameSize, nameSize-previousNameSize)) {
|
||||
return notifyFullnessToDelegate();
|
||||
}
|
||||
overrideSizeAtPosition(p, newRecordSize);
|
||||
overrideFullNameAtPosition(p+sizeof(record_size_t), fullName);
|
||||
notifyChangeToDelegate(record);
|
||||
m_lastRecordRetrieved = record;
|
||||
m_lastRecordRetrievedPointer = p;
|
||||
return Record::ErrorStatus::None;
|
||||
}
|
||||
return Record::ErrorStatus::RecordDoesNotExist;
|
||||
}
|
||||
|
||||
InternalStorage::Record::ErrorStatus InternalStorage::setBaseNameWithExtensionOfRecord(Record record, const char * baseName, const char * extension) {
|
||||
if (isBaseNameWithExtensionTaken(baseName, extension, &record)) {
|
||||
return Record::ErrorStatus::NameTaken;
|
||||
}
|
||||
size_t nameSize = sizeOfBaseNameAndExtension(baseName, extension);
|
||||
char * p = pointerOfRecord(record);
|
||||
if (p != nullptr) {
|
||||
size_t previousNameSize = strlen(fullNameOfRecordStarting(p))+1;
|
||||
record_size_t previousRecordSize = sizeOfRecordStarting(p);
|
||||
size_t newRecordSize = previousRecordSize-previousNameSize+nameSize;
|
||||
if (newRecordSize >= k_maxRecordSize || !slideBuffer(p+sizeof(record_size_t)+previousNameSize, nameSize-previousNameSize)) {
|
||||
return notifyFullnessToDelegate();
|
||||
}
|
||||
overrideSizeAtPosition(p, newRecordSize);
|
||||
char * fullNamePosition = p + sizeof(record_size_t);
|
||||
overrideBaseNameWithExtensionAtPosition(fullNamePosition, baseName, extension);
|
||||
// Recompute the CRC32
|
||||
record = Record(fullNamePosition);
|
||||
notifyChangeToDelegate(record);
|
||||
m_lastRecordRetrieved = record;
|
||||
m_lastRecordRetrievedPointer = p;
|
||||
return Record::ErrorStatus::None;
|
||||
}
|
||||
return Record::ErrorStatus::RecordDoesNotExist;
|
||||
}
|
||||
|
||||
InternalStorage::Record::Data InternalStorage::valueOfRecord(const Record record) {
|
||||
char * p = pointerOfRecord(record);
|
||||
if (p != nullptr) {
|
||||
const char * fullName = fullNameOfRecordStarting(p);
|
||||
record_size_t size = sizeOfRecordStarting(p);
|
||||
const void * value = valueOfRecordStarting(p);
|
||||
return {.buffer = value, .size = size-strlen(fullName)-1-sizeof(record_size_t)};
|
||||
}
|
||||
return {.buffer= nullptr, .size= 0};
|
||||
}
|
||||
|
||||
InternalStorage::Record::ErrorStatus InternalStorage::setValueOfRecord(Record record, Record::Data data) {
|
||||
char * p = pointerOfRecord(record);
|
||||
/* TODO: if data.buffer == p, assert that size hasn't change and do not do any
|
||||
* memcopy, but still notify the delegate. Beware of scripts and the accordion
|
||||
* routine.*/
|
||||
if (p != nullptr) {
|
||||
record_size_t previousRecordSize = sizeOfRecordStarting(p);
|
||||
const char * fullName = fullNameOfRecordStarting(p);
|
||||
size_t newRecordSize = sizeOfRecordWithFullName(fullName, data.size);
|
||||
if (newRecordSize >= k_maxRecordSize || !slideBuffer(p+previousRecordSize, newRecordSize-previousRecordSize)) {
|
||||
return notifyFullnessToDelegate();
|
||||
}
|
||||
record_size_t fullNameSize = strlen(fullName)+1;
|
||||
overrideSizeAtPosition(p, newRecordSize);
|
||||
overrideValueAtPosition(p+sizeof(record_size_t)+fullNameSize, data.buffer, data.size);
|
||||
notifyChangeToDelegate(record);
|
||||
m_lastRecordRetrieved = record;
|
||||
m_lastRecordRetrievedPointer = p;
|
||||
return Record::ErrorStatus::None;
|
||||
}
|
||||
return Record::ErrorStatus::RecordDoesNotExist;
|
||||
}
|
||||
|
||||
void InternalStorage::destroyRecord(Record record) {
|
||||
if (record.isNull()) {
|
||||
return;
|
||||
}
|
||||
char * p = pointerOfRecord(record);
|
||||
if (p != nullptr) {
|
||||
record_size_t previousRecordSize = sizeOfRecordStarting(p);
|
||||
slideBuffer(p+previousRecordSize, -previousRecordSize);
|
||||
notifyChangeToDelegate();
|
||||
}
|
||||
}
|
||||
|
||||
char * InternalStorage::pointerOfRecord(const Record record) const {
|
||||
if (record.isNull()) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!m_lastRecordRetrieved.isNull() && record == m_lastRecordRetrieved) {
|
||||
assert(m_lastRecordRetrievedPointer != nullptr);
|
||||
return m_lastRecordRetrievedPointer;
|
||||
}
|
||||
for (char * p : *this) {
|
||||
Record currentRecord(fullNameOfRecordStarting(p));
|
||||
if (record == currentRecord) {
|
||||
m_lastRecordRetrieved = record;
|
||||
m_lastRecordRetrievedPointer = p;
|
||||
return p;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
InternalStorage::record_size_t InternalStorage::sizeOfRecordStarting(char * start) const {
|
||||
return StorageHelper::unalignedShort(start);
|
||||
}
|
||||
|
||||
const char * InternalStorage::fullNameOfRecordStarting(char * start) const {
|
||||
return start+sizeof(record_size_t);
|
||||
}
|
||||
|
||||
const void * InternalStorage::valueOfRecordStarting(char * start) const {
|
||||
char * currentChar = start+sizeof(record_size_t);
|
||||
size_t fullNameLength = strlen(currentChar);
|
||||
return currentChar+fullNameLength+1;
|
||||
}
|
||||
|
||||
size_t InternalStorage::overrideSizeAtPosition(char * position, record_size_t size) {
|
||||
StorageHelper::writeUnalignedShort(size, position);
|
||||
return sizeof(record_size_t);
|
||||
}
|
||||
|
||||
size_t InternalStorage::overrideFullNameAtPosition(char * position, const char * fullName) {
|
||||
return strlcpy(position, fullName, strlen(fullName)+1) + 1;
|
||||
}
|
||||
|
||||
size_t InternalStorage::overrideBaseNameWithExtensionAtPosition(char * position, const char * baseName, const char * extension) {
|
||||
size_t result = strlcpy(position, baseName, strlen(baseName)+1); // strlcpy copies the null terminating char
|
||||
assert(UTF8Decoder::CharSizeOfCodePoint(k_dotChar) == 1);
|
||||
*(position+result) = k_dotChar; // Replace the null terminating char with a dot
|
||||
result++;
|
||||
result += strlcpy(position+result, extension, strlen(extension)+1);
|
||||
return result+1;
|
||||
}
|
||||
|
||||
size_t InternalStorage::overrideValueAtPosition(char * position, const void * data, record_size_t size) {
|
||||
memcpy(position, data, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
bool InternalStorage::isFullNameTaken(const char * fullName, const Record * recordToExclude) {
|
||||
Record r = Record(fullName);
|
||||
return isNameOfRecordTaken(r, recordToExclude);
|
||||
}
|
||||
|
||||
bool InternalStorage::isBaseNameWithExtensionTaken(const char * baseName, const char * extension, Record * recordToExclude) {
|
||||
Record r = Record(baseName, extension);
|
||||
return isNameOfRecordTaken(r, recordToExclude);
|
||||
}
|
||||
|
||||
bool InternalStorage::isNameOfRecordTaken(Record r, const Record * recordToExclude) {
|
||||
if (r == Record()) {
|
||||
/* If the CRC32 of fullName is 0, we want to refuse the name as it would
|
||||
* interfere with our escape case in the Record constructor, when the given
|
||||
* name is nullptr. */
|
||||
return true;
|
||||
}
|
||||
for (char * p : *this) {
|
||||
Record s(fullNameOfRecordStarting(p));
|
||||
if (recordToExclude && s == *recordToExclude) {
|
||||
continue;
|
||||
}
|
||||
if (s == r) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool InternalStorage::FullNameCompliant(const char * fullName) {
|
||||
// We check that there is one dot and one dot only.
|
||||
const char * dotChar = UTF8Helper::CodePointSearch(fullName, k_dotChar);
|
||||
if (*dotChar == 0) {
|
||||
return false;
|
||||
}
|
||||
if (*(UTF8Helper::CodePointSearch(dotChar+1, k_dotChar)) == 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool InternalStorage::FullNameHasExtension(const char * fullName, const char * extension, size_t extensionLength) {
|
||||
if (fullName == nullptr) {
|
||||
return false;
|
||||
}
|
||||
size_t fullNameLength = strlen(fullName);
|
||||
if (fullNameLength > extensionLength) {
|
||||
const char * ext = fullName + fullNameLength - extensionLength;
|
||||
if (UTF8Helper::PreviousCodePointIs(fullName, ext, k_dotChar) && strcmp(ext, extension) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
char * InternalStorage::endBuffer() {
|
||||
char * currentBuffer = m_buffer;
|
||||
for (char * p : *this) {
|
||||
currentBuffer += sizeOfRecordStarting(p);
|
||||
}
|
||||
return currentBuffer;
|
||||
}
|
||||
|
||||
size_t InternalStorage::sizeOfBaseNameAndExtension(const char * baseName, const char * extension) const {
|
||||
// +1 for the dot and +1 for the null terminating char
|
||||
return strlen(baseName)+1+strlen(extension)+1;
|
||||
}
|
||||
|
||||
size_t InternalStorage::sizeOfRecordWithBaseNameAndExtension(const char * baseName, const char * extension, size_t dataSize) const {
|
||||
return sizeOfBaseNameAndExtension(baseName, extension) + dataSize + sizeof(record_size_t);
|
||||
}
|
||||
|
||||
size_t InternalStorage::sizeOfRecordWithFullName(const char * fullName, size_t dataSize) const {
|
||||
size_t nameSize = strlen(fullName)+1;
|
||||
return nameSize+dataSize+sizeof(record_size_t);
|
||||
}
|
||||
|
||||
bool InternalStorage::slideBuffer(char * position, int delta) {
|
||||
if (delta > (int)availableSize()) {
|
||||
return false;
|
||||
}
|
||||
memmove(position+delta, position, endBuffer()+sizeof(record_size_t)-position);
|
||||
return true;
|
||||
}
|
||||
|
||||
InternalStorage::Record InternalStorage::privateRecordAndExtensionOfRecordBaseNamedWithExtensions(const char * baseName, const char * const extensions[], size_t numberOfExtensions, const char * * extensionResult, int baseNameLength) {
|
||||
size_t nameLength = baseNameLength < 0 ? strlen(baseName) : baseNameLength;
|
||||
{
|
||||
const char * lastRetrievedRecordFullName = fullNameOfRecordStarting(m_lastRecordRetrievedPointer);
|
||||
if (m_lastRecordRetrievedPointer != nullptr && strncmp(baseName, lastRetrievedRecordFullName, nameLength) == 0) {
|
||||
for (size_t i = 0; i < numberOfExtensions; i++) {
|
||||
if (strcmp(lastRetrievedRecordFullName+nameLength+1 /*+1 to pass the dot*/, extensions[i]) == 0) {
|
||||
assert(UTF8Helper::CodePointIs(lastRetrievedRecordFullName + nameLength, '.'));
|
||||
if (extensionResult != nullptr) {
|
||||
*extensionResult = extensions[i];
|
||||
}
|
||||
return m_lastRecordRetrieved;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (char * p : *this) {
|
||||
const char * currentName = fullNameOfRecordStarting(p);
|
||||
if (strncmp(baseName, currentName, nameLength) == 0) {
|
||||
for (size_t i = 0; i < numberOfExtensions; i++) {
|
||||
if (strcmp(currentName+nameLength+1 /*+1 to pass the dot*/, extensions[i]) == 0) {
|
||||
assert(UTF8Helper::CodePointIs(currentName + nameLength, '.'));
|
||||
if (extensionResult != nullptr) {
|
||||
*extensionResult = extensions[i];
|
||||
}
|
||||
return Record(currentName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (extensionResult != nullptr) {
|
||||
*extensionResult = nullptr;
|
||||
}
|
||||
return Record();
|
||||
}
|
||||
|
||||
InternalStorage::RecordIterator & InternalStorage::RecordIterator::operator++() {
|
||||
assert(m_recordStart);
|
||||
record_size_t size = StorageHelper::unalignedShort(m_recordStart);
|
||||
char * nextRecord = m_recordStart+size;
|
||||
record_size_t newRecordSize = StorageHelper::unalignedShort(nextRecord);
|
||||
m_recordStart = (newRecordSize == 0 ? nullptr : nextRecord);
|
||||
return *this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,291 +1,67 @@
|
||||
#include <ion.h>
|
||||
#include <string.h>
|
||||
#include <ion/storage.h>
|
||||
#include <assert.h>
|
||||
#include <new>
|
||||
#if ION_STORAGE_LOG
|
||||
#include<iostream>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <ion/unicode/utf8_helper.h>
|
||||
|
||||
namespace Ion {
|
||||
|
||||
/* We want to implement a simple singleton pattern, to make sure the storage is
|
||||
* initialized on first use, therefore preventing the static init order fiasco.
|
||||
* That being said, we rely on knowing where the storage resides in the device's
|
||||
* memory at compile time. Indeed, we want to advertise the static storage's
|
||||
* memory address in the PlatformInfo structure (so that we can read and write
|
||||
* it in DFU).
|
||||
* Using a "static Storage storage;" variable makes it a local symbol at best,
|
||||
* preventing the PlatformInfo from retrieving its address. And making the
|
||||
* Storage variable global yields the static init fiasco issue. We're working
|
||||
* around both issues by creating a global staticStorageArea buffer, and by
|
||||
* placement-newing the Storage into that area on first use. */
|
||||
|
||||
uint32_t staticStorageArea[sizeof(Storage)/sizeof(uint32_t)] = {0};
|
||||
|
||||
constexpr char Storage::expExtension[];
|
||||
constexpr char Storage::funcExtension[];
|
||||
constexpr char Storage::seqExtension[];
|
||||
constexpr char Storage::eqExtension[];
|
||||
|
||||
Storage * Storage::sharedStorage() {
|
||||
static Storage * storage = new (staticStorageArea) Storage();
|
||||
return storage;
|
||||
}
|
||||
|
||||
// RECORD
|
||||
|
||||
Storage::Record::Record(const char * fullName) {
|
||||
if (fullName == nullptr) {
|
||||
m_fullNameCRC32 = 0;
|
||||
return;
|
||||
}
|
||||
const char * dotChar = UTF8Helper::CodePointSearch(fullName, k_dotChar);
|
||||
// If no extension, return empty record
|
||||
if (*dotChar == 0 || *(dotChar+1) == 0) {
|
||||
m_fullNameCRC32 = 0;
|
||||
return;
|
||||
}
|
||||
new (this) Record(fullName, dotChar - fullName, dotChar+1, (fullName + strlen(fullName)) - (dotChar+1));
|
||||
}
|
||||
|
||||
Storage::Record::Record(const char * baseName, const char * extension) {
|
||||
if (baseName == nullptr) {
|
||||
assert(extension == nullptr);
|
||||
m_fullNameCRC32 = 0;
|
||||
return;
|
||||
}
|
||||
new (this) Record(baseName, strlen(baseName), extension, strlen(extension));
|
||||
}
|
||||
|
||||
|
||||
#if ION_STORAGE_LOG
|
||||
|
||||
void Storage::Record::log() {
|
||||
std::cout << "Name: " << fullName() << std::endl;
|
||||
std::cout << " Value (" << value().size << "): " << (char *)value().buffer << "\n\n" << std::endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32_t Storage::Record::checksum() {
|
||||
uint32_t crc32Results[2];
|
||||
crc32Results[0] = m_fullNameCRC32;
|
||||
Data data = value();
|
||||
crc32Results[1] = Ion::crc32Byte((const uint8_t *)data.buffer, data.size);
|
||||
return Ion::crc32Word(crc32Results, 2);
|
||||
}
|
||||
|
||||
Storage::Record::Record(const char * basename, int basenameLength, const char * extension, int extensionLength) {
|
||||
assert(basename != nullptr);
|
||||
assert(extension != nullptr);
|
||||
|
||||
// We compute the CRC32 of the CRC32s of the basename and the extension
|
||||
uint32_t crc32Results[2];
|
||||
crc32Results[0] = Ion::crc32Byte((const uint8_t *)basename, basenameLength);
|
||||
crc32Results[1] = Ion::crc32Byte((const uint8_t *)extension, extensionLength);
|
||||
m_fullNameCRC32 = Ion::crc32Word(crc32Results, 2);
|
||||
}
|
||||
|
||||
// STORAGE
|
||||
|
||||
#if ION_STORAGE_LOG
|
||||
void Storage::log() {
|
||||
for (char * p : *this) {
|
||||
const char * currentName = fullNameOfRecordStarting(p);
|
||||
Record(currentName).log();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t Storage::availableSize() {
|
||||
if (m_trashRecord != NULL) {
|
||||
return realAvailableSize() + sizeof(record_size_t) + m_trashRecord.value().size;
|
||||
if (m_trashRecord != Record()) {
|
||||
int bufferSize = 0;
|
||||
for (char * p : *this) {
|
||||
if (Record(fullNameOfRecordStarting(p)) != m_trashRecord) {
|
||||
bufferSize += sizeOfRecordStarting(p);
|
||||
}
|
||||
}
|
||||
return k_storageSize-bufferSize-sizeof(record_size_t);
|
||||
} else {
|
||||
return realAvailableSize();
|
||||
return InternalStorage::availableSize();
|
||||
}
|
||||
}
|
||||
|
||||
size_t Storage::realAvailableSize() {
|
||||
/* TODO maybe do: availableSize(char ** endBuffer) to get the endBuffer if it
|
||||
* is needed after calling availableSize */
|
||||
assert(k_storageSize >= (endBuffer() - m_buffer) + sizeof(record_size_t));
|
||||
return k_storageSize-(endBuffer()-m_buffer)-sizeof(record_size_t);
|
||||
}
|
||||
|
||||
size_t Storage::putAvailableSpaceAtEndOfRecord(Storage::Record r) {
|
||||
char * p = pointerOfRecord(r);
|
||||
size_t previousRecordSize = sizeOfRecordStarting(p);
|
||||
size_t availableStorageSize = realAvailableSize();
|
||||
char * nextRecord = p + previousRecordSize;
|
||||
memmove(nextRecord + availableStorageSize,
|
||||
nextRecord,
|
||||
(m_buffer + k_storageSize - availableStorageSize) - nextRecord);
|
||||
size_t newRecordSize = previousRecordSize + availableStorageSize;
|
||||
overrideSizeAtPosition(p, (record_size_t)newRecordSize);
|
||||
return newRecordSize;
|
||||
size_t Storage::putAvailableSpaceAtEndOfRecord(Record r) {
|
||||
emptyTrash();
|
||||
return InternalStorage::putAvailableSpaceAtEndOfRecord(r);
|
||||
}
|
||||
|
||||
void Storage::getAvailableSpaceFromEndOfRecord(Record r, size_t recordAvailableSpace) {
|
||||
char * p = pointerOfRecord(r);
|
||||
size_t previousRecordSize = sizeOfRecordStarting(p);
|
||||
char * nextRecord = p + previousRecordSize;
|
||||
memmove(nextRecord - recordAvailableSpace,
|
||||
nextRecord,
|
||||
m_buffer + k_storageSize - nextRecord);
|
||||
overrideSizeAtPosition(p, (record_size_t)(previousRecordSize - recordAvailableSpace));
|
||||
emptyTrash();
|
||||
InternalStorage::getAvailableSpaceFromEndOfRecord(r, recordAvailableSpace);
|
||||
}
|
||||
|
||||
uint32_t Storage::checksum() {
|
||||
return Ion::crc32Byte((const uint8_t *) m_buffer, endBuffer()-m_buffer);
|
||||
}
|
||||
|
||||
void Storage::notifyChangeToDelegate(const Record record) const {
|
||||
m_lastRecordRetrieved = Record(nullptr);
|
||||
m_lastRecordRetrievedPointer = nullptr;
|
||||
if (m_delegate != nullptr) {
|
||||
m_delegate->storageDidChangeForRecord(record);
|
||||
int Storage::numberOfRecordsWithExtension(const char * extension) {
|
||||
int trashRecord = 0;
|
||||
if (FullNameHasExtension(m_trashRecord.fullName(), extension, strlen(extension))) {
|
||||
trashRecord = 1;
|
||||
}
|
||||
}
|
||||
|
||||
Storage::Record::ErrorStatus Storage::notifyFullnessToDelegate() const {
|
||||
if (m_delegate != nullptr) {
|
||||
m_delegate->storageIsFull();
|
||||
}
|
||||
return Record::ErrorStatus::NotEnoughSpaceAvailable;
|
||||
return InternalStorage::numberOfRecordsWithExtension(extension) - trashRecord;
|
||||
}
|
||||
|
||||
Storage::Record::ErrorStatus Storage::createRecordWithFullName(const char * fullName, const void * data, size_t size) {
|
||||
emptyTrash();
|
||||
size_t recordSize = sizeOfRecordWithFullName(fullName, size);
|
||||
if (recordSize >= k_maxRecordSize || recordSize > availableSize()) {
|
||||
return notifyFullnessToDelegate();
|
||||
}
|
||||
if (isFullNameTaken(fullName)) {
|
||||
return Record::ErrorStatus::NameTaken;
|
||||
}
|
||||
// Find the end of data
|
||||
char * newRecordAddress = endBuffer();
|
||||
char * newRecord = newRecordAddress;
|
||||
// Fill totalSize
|
||||
newRecord += overrideSizeAtPosition(newRecord, (record_size_t)recordSize);
|
||||
// Fill name
|
||||
newRecord += overrideFullNameAtPosition(newRecord, fullName);
|
||||
// Fill data
|
||||
newRecord += overrideValueAtPosition(newRecord, data, size);
|
||||
// Next Record is null-sized
|
||||
overrideSizeAtPosition(newRecord, 0);
|
||||
Record r = Record(fullName);
|
||||
notifyChangeToDelegate(r);
|
||||
m_lastRecordRetrieved = r;
|
||||
m_lastRecordRetrievedPointer = newRecordAddress;
|
||||
return Record::ErrorStatus::None;
|
||||
return InternalStorage::createRecordWithFullName(fullName, data, size);
|
||||
}
|
||||
|
||||
Storage::Record::ErrorStatus Storage::createRecordWithExtension(const char * baseName, const char * extension, const void * data, size_t size) {
|
||||
emptyTrash();
|
||||
size_t recordSize = sizeOfRecordWithBaseNameAndExtension(baseName, extension, size);
|
||||
if (recordSize >= k_maxRecordSize || recordSize > availableSize()) {
|
||||
return notifyFullnessToDelegate();
|
||||
}
|
||||
if (isBaseNameWithExtensionTaken(baseName, extension)) {
|
||||
return Record::ErrorStatus::NameTaken;
|
||||
}
|
||||
// Find the end of data
|
||||
char * newRecordAddress = endBuffer();
|
||||
char * newRecord = newRecordAddress;
|
||||
// Fill totalSize
|
||||
newRecord += overrideSizeAtPosition(newRecord, (record_size_t)recordSize);
|
||||
// Fill name
|
||||
newRecord += overrideBaseNameWithExtensionAtPosition(newRecord, baseName, extension);
|
||||
// Fill data
|
||||
newRecord += overrideValueAtPosition(newRecord, data, size);
|
||||
// Next Record is null-sized
|
||||
overrideSizeAtPosition(newRecord, 0);
|
||||
Record r = Record(fullNameOfRecordStarting(newRecordAddress));
|
||||
notifyChangeToDelegate(r);
|
||||
m_lastRecordRetrieved = r;
|
||||
m_lastRecordRetrievedPointer = newRecordAddress;
|
||||
return Record::ErrorStatus::None;
|
||||
return InternalStorage::createRecordWithExtension(baseName, extension, data, size);
|
||||
}
|
||||
|
||||
int Storage::numberOfRecordsWithExtension(const char * extension) {
|
||||
int count = 0;
|
||||
size_t extensionLength = strlen(extension);
|
||||
for (char * p : *this) {
|
||||
const char * name = fullNameOfRecordStarting(p);
|
||||
if (FullNameHasExtension(name, extension, extensionLength) && Record(name) != m_trashRecord) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
bool Storage::hasRecord(Record r) {
|
||||
return InternalStorage::hasRecord(r) && r != m_trashRecord;
|
||||
}
|
||||
|
||||
int Storage::numberOfRecords() {
|
||||
return realNumberOfRecords() - (m_trashRecord == NULL ? 0 : 1);
|
||||
}
|
||||
|
||||
int Storage::realNumberOfRecords() {
|
||||
int count = 0;
|
||||
for (char * p : *this) {
|
||||
const char * name = fullNameOfRecordStarting(p);
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
Storage::Record Storage::realRecordAtIndex(int index) {
|
||||
int currentIndex = -1;
|
||||
const char * name = nullptr;
|
||||
char * recordAddress = nullptr;
|
||||
for (char * p : *this) {
|
||||
const char * currentName = fullNameOfRecordStarting(p);
|
||||
currentIndex++;
|
||||
if (currentIndex == index) {
|
||||
recordAddress = p;
|
||||
name = currentName;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (name == nullptr) {
|
||||
return Record();
|
||||
}
|
||||
Record r = Record(name);
|
||||
m_lastRecordRetrieved = r;
|
||||
m_lastRecordRetrievedPointer = recordAddress;
|
||||
return Record(name);
|
||||
}
|
||||
|
||||
|
||||
Storage::Record Storage::recordAtIndex(int index) {
|
||||
int currentIndex = -1;
|
||||
const char * name = nullptr;
|
||||
char * recordAddress = nullptr;
|
||||
for (char * p : *this) {
|
||||
const char * currentName = fullNameOfRecordStarting(p);
|
||||
Record r = Record(currentName);
|
||||
if (r == m_trashRecord) {
|
||||
continue;
|
||||
}
|
||||
currentIndex++;
|
||||
if (currentIndex == index) {
|
||||
recordAddress = p;
|
||||
name = currentName;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (name == nullptr) {
|
||||
return Record();
|
||||
}
|
||||
Record r = Record(name);
|
||||
m_lastRecordRetrieved = r;
|
||||
m_lastRecordRetrievedPointer = recordAddress;
|
||||
return Record(name);
|
||||
}
|
||||
|
||||
void Storage::emptyTrash() {
|
||||
if (m_trashRecord != NULL) {
|
||||
realDestroyRecord(m_trashRecord);
|
||||
m_trashRecord = NULL;
|
||||
}
|
||||
void Storage::destroyRecord(Record record) {
|
||||
emptyTrash();
|
||||
m_trashRecord = record;
|
||||
}
|
||||
|
||||
Storage::Record Storage::recordWithExtensionAtIndex(const char * extension, int index) {
|
||||
@@ -307,397 +83,98 @@ Storage::Record Storage::recordWithExtensionAtIndex(const char * extension, int
|
||||
if (name == nullptr) {
|
||||
return Record();
|
||||
}
|
||||
Record r = Record(name);
|
||||
Storage::Record r = Record(name);
|
||||
m_lastRecordRetrieved = r;
|
||||
m_lastRecordRetrievedPointer = recordAddress;
|
||||
return Record(name);
|
||||
}
|
||||
|
||||
Storage::Record Storage::recordNamed(const char * fullName) {
|
||||
if (fullName == nullptr) {
|
||||
return Record();
|
||||
}
|
||||
Record r = Record(fullName);
|
||||
char * p = pointerOfRecord(r);
|
||||
if (p != nullptr) {
|
||||
return r;
|
||||
}
|
||||
return Record();
|
||||
Storage::Record r = InternalStorage::recordNamed(fullName);
|
||||
return r == m_trashRecord ? Record() : r;
|
||||
}
|
||||
|
||||
Storage::Record Storage::recordBaseNamedWithExtension(const char * baseName, const char * extension) {
|
||||
const char * extensions[1] = {extension};
|
||||
return recordBaseNamedWithExtensions(baseName, extensions, 1);
|
||||
Storage::Record r = InternalStorage::recordBaseNamedWithExtension(baseName, extension);
|
||||
return r == m_trashRecord ? Record() : r;
|
||||
}
|
||||
|
||||
Storage::Record Storage::recordBaseNamedWithExtensions(const char * baseName, const char * const extensions[], size_t numberOfExtensions) {
|
||||
return privateRecordAndExtensionOfRecordBaseNamedWithExtensions(baseName, extensions, numberOfExtensions);
|
||||
Storage::Record Storage::recordBaseNamedWithExtensions(const char * baseName, const char * const extension[], size_t numberOfExtensions) {
|
||||
Storage::Record r = InternalStorage::recordBaseNamedWithExtensions(baseName, extension, numberOfExtensions);
|
||||
return r == m_trashRecord ? Record() : r;
|
||||
}
|
||||
|
||||
const char * Storage::extensionOfRecordBaseNamedWithExtensions(const char * baseName, int baseNameLength, const char * const extensions[], size_t numberOfExtensions) {
|
||||
const char * result = nullptr;
|
||||
privateRecordAndExtensionOfRecordBaseNamedWithExtensions(baseName, extensions, numberOfExtensions, &result, baseNameLength);
|
||||
return result;
|
||||
}
|
||||
|
||||
void Storage::destroyAllRecords() {
|
||||
overrideSizeAtPosition(m_buffer, 0);
|
||||
notifyChangeToDelegate();
|
||||
}
|
||||
|
||||
void Storage::destroyRecordWithBaseNameAndExtension(const char * baseName, const char * extension) {
|
||||
recordBaseNamedWithExtension(baseName, extension).destroy();
|
||||
}
|
||||
|
||||
void Storage::destroyRecordsWithExtension(const char * extension) {
|
||||
size_t extensionLength = strlen(extension);
|
||||
char * currentRecordStart = (char *)m_buffer;
|
||||
bool didChange = false;
|
||||
while (currentRecordStart != nullptr && sizeOfRecordStarting(currentRecordStart) != 0) {
|
||||
const char * currentFullName = fullNameOfRecordStarting(currentRecordStart);
|
||||
if (FullNameHasExtension(currentFullName, extension, extensionLength)) {
|
||||
Record currentRecord(currentFullName);
|
||||
currentRecord.destroy();
|
||||
didChange = true;
|
||||
continue;
|
||||
}
|
||||
currentRecordStart = *(RecordIterator(currentRecordStart).operator++());
|
||||
}
|
||||
if (didChange) {
|
||||
notifyChangeToDelegate();
|
||||
}
|
||||
}
|
||||
|
||||
// PRIVATE
|
||||
|
||||
Storage::Storage() :
|
||||
m_magicHeader(Magic),
|
||||
m_buffer(),
|
||||
m_magicFooter(Magic),
|
||||
m_delegate(nullptr),
|
||||
m_lastRecordRetrieved(nullptr),
|
||||
m_lastRecordRetrievedPointer(nullptr),
|
||||
m_trashRecord(NULL)
|
||||
{
|
||||
assert(m_magicHeader == Magic);
|
||||
assert(m_magicFooter == Magic);
|
||||
// Set the size of the first record to 0
|
||||
overrideSizeAtPosition(m_buffer, 0);
|
||||
}
|
||||
|
||||
const char * Storage::fullNameOfRecord(const Record record) {
|
||||
char * p = pointerOfRecord(record);
|
||||
if (p != nullptr) {
|
||||
return fullNameOfRecordStarting(p);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Storage::Record::ErrorStatus Storage::setFullNameOfRecord(const Record record, const char * fullName) {
|
||||
if (!FullNameCompliant(fullName)) {
|
||||
return Record::ErrorStatus::NonCompliantName;
|
||||
}
|
||||
if (isFullNameTaken(fullName, &record)) {
|
||||
return Record::ErrorStatus::NameTaken;
|
||||
}
|
||||
size_t nameSize = strlen(fullName) + 1;
|
||||
char * p = pointerOfRecord(record);
|
||||
if (p != nullptr) {
|
||||
size_t previousNameSize = strlen(fullNameOfRecordStarting(p))+1;
|
||||
record_size_t previousRecordSize = sizeOfRecordStarting(p);
|
||||
size_t newRecordSize = previousRecordSize-previousNameSize+nameSize;
|
||||
if (newRecordSize >= k_maxRecordSize || !slideBuffer(p+sizeof(record_size_t)+previousNameSize, nameSize-previousNameSize)) {
|
||||
return notifyFullnessToDelegate();
|
||||
}
|
||||
overrideSizeAtPosition(p, newRecordSize);
|
||||
overrideFullNameAtPosition(p+sizeof(record_size_t), fullName);
|
||||
notifyChangeToDelegate(record);
|
||||
m_lastRecordRetrieved = record;
|
||||
m_lastRecordRetrievedPointer = p;
|
||||
return Record::ErrorStatus::None;
|
||||
}
|
||||
return Record::ErrorStatus::RecordDoesNotExist;
|
||||
}
|
||||
|
||||
Storage::Record::ErrorStatus Storage::setBaseNameWithExtensionOfRecord(Record record, const char * baseName, const char * extension) {
|
||||
if (isBaseNameWithExtensionTaken(baseName, extension, &record)) {
|
||||
return Record::ErrorStatus::NameTaken;
|
||||
}
|
||||
size_t nameSize = sizeOfBaseNameAndExtension(baseName, extension);
|
||||
char * p = pointerOfRecord(record);
|
||||
if (p != nullptr) {
|
||||
size_t previousNameSize = strlen(fullNameOfRecordStarting(p))+1;
|
||||
record_size_t previousRecordSize = sizeOfRecordStarting(p);
|
||||
size_t newRecordSize = previousRecordSize-previousNameSize+nameSize;
|
||||
if (newRecordSize >= k_maxRecordSize || !slideBuffer(p+sizeof(record_size_t)+previousNameSize, nameSize-previousNameSize)) {
|
||||
return notifyFullnessToDelegate();
|
||||
}
|
||||
overrideSizeAtPosition(p, newRecordSize);
|
||||
char * fullNamePosition = p + sizeof(record_size_t);
|
||||
overrideBaseNameWithExtensionAtPosition(fullNamePosition, baseName, extension);
|
||||
// Recompute the CRC32
|
||||
record = Record(fullNamePosition);
|
||||
notifyChangeToDelegate(record);
|
||||
m_lastRecordRetrieved = record;
|
||||
m_lastRecordRetrievedPointer = p;
|
||||
return Record::ErrorStatus::None;
|
||||
}
|
||||
return Record::ErrorStatus::RecordDoesNotExist;
|
||||
}
|
||||
|
||||
Storage::Record::Data Storage::valueOfRecord(const Record record) {
|
||||
char * p = pointerOfRecord(record);
|
||||
if (p != nullptr) {
|
||||
const char * fullName = fullNameOfRecordStarting(p);
|
||||
record_size_t size = sizeOfRecordStarting(p);
|
||||
const void * value = valueOfRecordStarting(p);
|
||||
return {.buffer = value, .size = size-strlen(fullName)-1-sizeof(record_size_t)};
|
||||
}
|
||||
return {.buffer= nullptr, .size= 0};
|
||||
}
|
||||
|
||||
Storage::Record::ErrorStatus Storage::setValueOfRecord(Record record, Record::Data data) {
|
||||
char * p = pointerOfRecord(record);
|
||||
/* TODO: if data.buffer == p, assert that size hasn't change and do not do any
|
||||
* memcopy, but still notify the delegate. Beware of scripts and the accordion
|
||||
* routine.*/
|
||||
if (p != nullptr) {
|
||||
record_size_t previousRecordSize = sizeOfRecordStarting(p);
|
||||
const char * fullName = fullNameOfRecordStarting(p);
|
||||
size_t newRecordSize = sizeOfRecordWithFullName(fullName, data.size);
|
||||
if (newRecordSize >= k_maxRecordSize || !slideBuffer(p+previousRecordSize, newRecordSize-previousRecordSize)) {
|
||||
return notifyFullnessToDelegate();
|
||||
}
|
||||
record_size_t fullNameSize = strlen(fullName)+1;
|
||||
overrideSizeAtPosition(p, newRecordSize);
|
||||
overrideValueAtPosition(p+sizeof(record_size_t)+fullNameSize, data.buffer, data.size);
|
||||
notifyChangeToDelegate(record);
|
||||
m_lastRecordRetrieved = record;
|
||||
m_lastRecordRetrievedPointer = p;
|
||||
return Record::ErrorStatus::None;
|
||||
}
|
||||
return Record::ErrorStatus::RecordDoesNotExist;
|
||||
}
|
||||
|
||||
|
||||
void Storage::reinsertTrash(const char * extension) {
|
||||
if (m_trashRecord != NULL) {
|
||||
char * p = pointerOfRecord(m_trashRecord);
|
||||
const char * fullName = fullNameOfRecordStarting(p);
|
||||
if (FullNameHasExtension(fullName, extension, strlen(extension))) {
|
||||
m_trashRecord = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Storage::destroyRecord(Record record) {
|
||||
emptyTrash();
|
||||
m_trashRecord = record;
|
||||
}
|
||||
|
||||
void Storage::realDestroyRecord(Record record) {
|
||||
if (record.isNull()) {
|
||||
return;
|
||||
}
|
||||
char * p = pointerOfRecord(record);
|
||||
if (p != nullptr) {
|
||||
record_size_t previousRecordSize = sizeOfRecordStarting(p);
|
||||
slideBuffer(p+previousRecordSize, -previousRecordSize);
|
||||
notifyChangeToDelegate();
|
||||
}
|
||||
}
|
||||
|
||||
char * Storage::pointerOfRecord(const Record record) const {
|
||||
if (record.isNull()) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!m_lastRecordRetrieved.isNull() && record == m_lastRecordRetrieved) {
|
||||
assert(m_lastRecordRetrievedPointer != nullptr);
|
||||
return m_lastRecordRetrievedPointer;
|
||||
}
|
||||
for (char * p : *this) {
|
||||
Record currentRecord(fullNameOfRecordStarting(p));
|
||||
if (record == currentRecord) {
|
||||
m_lastRecordRetrieved = record;
|
||||
m_lastRecordRetrievedPointer = p;
|
||||
return p;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Storage::record_size_t Storage::sizeOfRecordStarting(char * start) const {
|
||||
return StorageHelper::unalignedShort(start);
|
||||
}
|
||||
|
||||
const char * Storage::fullNameOfRecordStarting(char * start) const {
|
||||
return start+sizeof(record_size_t);
|
||||
}
|
||||
|
||||
const void * Storage::valueOfRecordStarting(char * start) const {
|
||||
char * currentChar = start+sizeof(record_size_t);
|
||||
size_t fullNameLength = strlen(currentChar);
|
||||
return currentChar+fullNameLength+1;
|
||||
}
|
||||
|
||||
size_t Storage::overrideSizeAtPosition(char * position, record_size_t size) {
|
||||
StorageHelper::writeUnalignedShort(size, position);
|
||||
return sizeof(record_size_t);
|
||||
}
|
||||
|
||||
size_t Storage::overrideFullNameAtPosition(char * position, const char * fullName) {
|
||||
return strlcpy(position, fullName, strlen(fullName)+1) + 1;
|
||||
}
|
||||
|
||||
size_t Storage::overrideBaseNameWithExtensionAtPosition(char * position, const char * baseName, const char * extension) {
|
||||
size_t result = strlcpy(position, baseName, strlen(baseName)+1); // strlcpy copies the null terminating char
|
||||
assert(UTF8Decoder::CharSizeOfCodePoint(k_dotChar) == 1);
|
||||
*(position+result) = k_dotChar; // Replace the null terminating char with a dot
|
||||
result++;
|
||||
result += strlcpy(position+result, extension, strlen(extension)+1);
|
||||
return result+1;
|
||||
}
|
||||
|
||||
size_t Storage::overrideValueAtPosition(char * position, const void * data, record_size_t size) {
|
||||
memcpy(position, data, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
bool Storage::isFullNameTaken(const char * fullName, const Record * recordToExclude) {
|
||||
Record r = Record(fullName);
|
||||
return isNameOfRecordTaken(r, recordToExclude);
|
||||
}
|
||||
|
||||
bool Storage::isBaseNameWithExtensionTaken(const char * baseName, const char * extension, Record * recordToExclude) {
|
||||
Record r = Record(baseName, extension);
|
||||
return isNameOfRecordTaken(r, recordToExclude);
|
||||
}
|
||||
|
||||
bool Storage::isNameOfRecordTaken(Record r, const Record * recordToExclude) {
|
||||
if (r == Record()) {
|
||||
/* If the CRC32 of fullName is 0, we want to refuse the name as it would
|
||||
* interfere with our escape case in the Record constructor, when the given
|
||||
* name is nullptr. */
|
||||
return true;
|
||||
}
|
||||
for (char * p : *this) {
|
||||
Record s(fullNameOfRecordStarting(p));
|
||||
if (recordToExclude && s == *recordToExclude) {
|
||||
continue;
|
||||
}
|
||||
if (s == r && s != m_trashRecord) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Storage::FullNameCompliant(const char * fullName) {
|
||||
// We check that there is one dot and one dot only.
|
||||
const char * dotChar = UTF8Helper::CodePointSearch(fullName, k_dotChar);
|
||||
if (*dotChar == 0) {
|
||||
return false;
|
||||
}
|
||||
if (*(UTF8Helper::CodePointSearch(dotChar+1, k_dotChar)) == 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Storage::FullNameHasExtension(const char * fullName, const char * extension, size_t extensionLength) {
|
||||
if (fullName == nullptr) {
|
||||
return false;
|
||||
}
|
||||
size_t fullNameLength = strlen(fullName);
|
||||
if (fullNameLength > extensionLength) {
|
||||
const char * ext = fullName + fullNameLength - extensionLength;
|
||||
if (UTF8Helper::PreviousCodePointIs(fullName, ext, k_dotChar) && strcmp(ext, extension) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
char * Storage::endBuffer() {
|
||||
char * currentBuffer = m_buffer;
|
||||
for (char * p : *this) {
|
||||
currentBuffer += sizeOfRecordStarting(p);
|
||||
}
|
||||
return currentBuffer;
|
||||
}
|
||||
|
||||
size_t Storage::sizeOfBaseNameAndExtension(const char * baseName, const char * extension) const {
|
||||
// +1 for the dot and +1 for the null terminating char
|
||||
return strlen(baseName)+1+strlen(extension)+1;
|
||||
}
|
||||
|
||||
size_t Storage::sizeOfRecordWithBaseNameAndExtension(const char * baseName, const char * extension, size_t dataSize) const {
|
||||
return sizeOfBaseNameAndExtension(baseName, extension) + dataSize + sizeof(record_size_t);
|
||||
}
|
||||
|
||||
size_t Storage::sizeOfRecordWithFullName(const char * fullName, size_t dataSize) const {
|
||||
size_t nameSize = strlen(fullName)+1;
|
||||
return nameSize+dataSize+sizeof(record_size_t);
|
||||
}
|
||||
|
||||
bool Storage::slideBuffer(char * position, int delta) {
|
||||
if (delta > (int)realAvailableSize()) {
|
||||
emptyTrash();
|
||||
if (delta > (int)realAvailableSize()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
memmove(position+delta, position, endBuffer()+sizeof(record_size_t)-position);
|
||||
return true;
|
||||
}
|
||||
|
||||
Storage::Record Storage::privateRecordAndExtensionOfRecordBaseNamedWithExtensions(const char * baseName, const char * const extensions[], size_t numberOfExtensions, const char * * extensionResult, int baseNameLength) {
|
||||
const char * Storage::extensionOfRecordBaseNamedWithExtensions(const char * baseName, int baseNameLength, const char * const extension[], size_t numberOfExtensions) {
|
||||
size_t nameLength = baseNameLength < 0 ? strlen(baseName) : baseNameLength;
|
||||
{
|
||||
const char * lastRetrievedRecordFullName = fullNameOfRecordStarting(m_lastRecordRetrievedPointer);
|
||||
if (m_lastRecordRetrievedPointer != nullptr && strncmp(baseName, lastRetrievedRecordFullName, nameLength) == 0 && Record(lastRetrievedRecordFullName) == m_trashRecord) {
|
||||
if (m_lastRecordRetrievedPointer != nullptr && strncmp(baseName, lastRetrievedRecordFullName, nameLength) == 0 && Record(lastRetrievedRecordFullName) != m_trashRecord) {
|
||||
for (size_t i = 0; i < numberOfExtensions; i++) {
|
||||
if (strcmp(lastRetrievedRecordFullName+nameLength+1 /*+1 to pass the dot*/, extensions[i]) == 0) {
|
||||
if (strcmp(lastRetrievedRecordFullName+nameLength+1 /*+1 to pass the dot*/, extension[i]) == 0) {
|
||||
assert(UTF8Helper::CodePointIs(lastRetrievedRecordFullName + nameLength, '.'));
|
||||
if (extensionResult != nullptr) {
|
||||
*extensionResult = extensions[i];
|
||||
}
|
||||
return m_lastRecordRetrieved;
|
||||
return extension[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (char * p : *this) {
|
||||
const char * currentName = fullNameOfRecordStarting(p);
|
||||
if (strncmp(baseName, currentName, nameLength) == 0) {
|
||||
if (Record(currentName) == m_trashRecord) {
|
||||
continue;
|
||||
}
|
||||
if (strncmp(baseName, currentName, nameLength) == 0 && Record(currentName) != m_trashRecord) {
|
||||
for (size_t i = 0; i < numberOfExtensions; i++) {
|
||||
if (strcmp(currentName+nameLength+1 /*+1 to pass the dot*/, extensions[i]) == 0) {
|
||||
if (strcmp(currentName+nameLength+1 /*+1 to pass the dot*/, extension[i]) == 0) {
|
||||
assert(UTF8Helper::CodePointIs(currentName + nameLength, '.'));
|
||||
if (extensionResult != nullptr) {
|
||||
*extensionResult = extensions[i];
|
||||
}
|
||||
return Record(currentName);
|
||||
return extension[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (extensionResult != nullptr) {
|
||||
*extensionResult = nullptr;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int Storage::numberOfRecords() {
|
||||
return InternalStorage::numberOfRecords() - (m_trashRecord != NULL ? 1 : 0);
|
||||
}
|
||||
|
||||
InternalStorage::Record Storage::recordAtIndex(int index) {
|
||||
int currentIndex = -1;
|
||||
const char * name = nullptr;
|
||||
char * recordAddress = nullptr;
|
||||
for (char * p : *this) {
|
||||
const char * currentName = fullNameOfRecordStarting(p);
|
||||
if (Record(currentName) != m_trashRecord) {
|
||||
currentIndex++;
|
||||
if (currentIndex == index) {
|
||||
recordAddress = p;
|
||||
name = currentName;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Record();
|
||||
if (name == nullptr) {
|
||||
return Record();
|
||||
}
|
||||
Record r = Record(name);
|
||||
m_lastRecordRetrieved = r;
|
||||
m_lastRecordRetrievedPointer = recordAddress;
|
||||
return Record(name);
|
||||
}
|
||||
|
||||
Storage::RecordIterator & Storage::RecordIterator::operator++() {
|
||||
assert(m_recordStart);
|
||||
record_size_t size = StorageHelper::unalignedShort(m_recordStart);
|
||||
char * nextRecord = m_recordStart+size;
|
||||
record_size_t newRecordSize = StorageHelper::unalignedShort(nextRecord);
|
||||
m_recordStart = (newRecordSize == 0 ? nullptr : nextRecord);
|
||||
return *this;
|
||||
void Storage::reinsertTrash(const char * extension) {
|
||||
if (!m_trashRecord.isNull()) {
|
||||
char * p = pointerOfRecord(m_trashRecord);
|
||||
const char * fullName = fullNameOfRecordStarting(p);
|
||||
if (FullNameHasExtension(fullName, extension, strlen(extension))) {
|
||||
m_trashRecord = Record();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Storage::emptyTrash() {
|
||||
if (!m_trashRecord.isNull()) {
|
||||
InternalStorage::destroyRecord(m_trashRecord);
|
||||
m_trashRecord = Record();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -324,7 +324,9 @@ uint32_t ExtendedCodePoints[] = {
|
||||
0x3c7, // χ // GREEK SMALL LETTER KHI
|
||||
0x3c8, // ψ // GREEK SMALL LETTER PSI
|
||||
0x3c9, // ω // GREEK SMALL LETTER OMEGA
|
||||
0x454, // є // CYRILLIC SMALL LETTER UKRAINIAN LE
|
||||
0x1d07, // ᴇ // LATIN LETTER SMALL CAPITAL E
|
||||
0x2026, // … // HORIZONTAL ELLIPSIS
|
||||
0x212f, // ℯ // SCRIPT SMALL E
|
||||
0x2190, // ← // BACKWARD ARROW (leftarrow)
|
||||
0x2191, // ↑ // TOP ARROW (uparrow)
|
||||
@@ -332,6 +334,10 @@ uint32_t ExtendedCodePoints[] = {
|
||||
0x2193, // ↓ // BOTTOM ARROW (downarrow)
|
||||
0x2194, // ↔ // BACKWARD FORWARD ARROW (leftrightarrow)
|
||||
0x2195, // ↕ // TOP BOTTOM ARROW (updownarrow)
|
||||
0x2196, // ↖ // NORDWEST ARROW (nwarrow)
|
||||
0x2197, // ↗ // NORDEST ARROW (nearrow)
|
||||
0x2198, // ↘ // SOUTHWEST ARROW (swarrow)
|
||||
0x2199, // ↙ // SOUTHEST ARROW (searrow)
|
||||
0x21d0, // ⇐ // DOUBLE BACKWARD ARROW (Leftarrow)
|
||||
0x21d1, // ⇑ // DOUBLE TOP ARROW (Uparrow)
|
||||
0x21d2, // ⇒ // DOUBLE FORWARD ARROW (Rightarrow)
|
||||
@@ -348,6 +354,7 @@ uint32_t ExtendedCodePoints[] = {
|
||||
0x2261, // ≡ // IS CONGRUENT TO
|
||||
0x2264, // ≤ // LESS-THAN OR EQUAL TO
|
||||
0x2265, // ≥ // GREATER-THAN OR EQUAL TO
|
||||
0x2505, // ┅ // BOX DRAWING EQU HEAVY DASH HORIZONTAL
|
||||
0xFFFD, // <20> // REPLACEMENT CHARACTER
|
||||
0x1d422, // 𝐢 // MATHEMATICAL BOLD SMALL I"
|
||||
};
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user