From 72a25ec26d256f6c4020c0fed792f46b8b5c9bf4 Mon Sep 17 00:00:00 2001 From: Laury Date: Sun, 13 Mar 2022 21:31:10 +0100 Subject: [PATCH 01/10] [ion] Rework of storage trash --- ion/Makefile | 1 + ion/include/ion/internal_storage.h | 218 +++++++++ ion/include/ion/storage.h | 217 +-------- ion/src/shared/internal_storage.cpp | 647 ++++++++++++++++++++++++++ ion/src/shared/storage.cpp | 691 ++++------------------------ python/port/mod/ion/file.cpp | 16 +- 6 files changed, 969 insertions(+), 821 deletions(-) create mode 100644 ion/include/ion/internal_storage.h create mode 100644 ion/src/shared/internal_storage.cpp diff --git a/ion/Makefile b/ion/Makefile index 1b04baf69..c53ae60ef 100644 --- a/ion/Makefile +++ b/ion/Makefile @@ -31,6 +31,7 @@ ion_src += $(addprefix ion/src/shared/, \ events.cpp \ events_keyboard.cpp \ events_modifier.cpp \ + internal_storage.cpp \ platform_info.cpp \ rtc.cpp \ stack_position.cpp \ diff --git a/ion/include/ion/internal_storage.h b/ion/include/ion/internal_storage.h new file mode 100644 index 000000000..ead06746a --- /dev/null +++ b/ion/include/ion/internal_storage.h @@ -0,0 +1,218 @@ +#ifndef ION_INTERNAL_STORAGE_H +#define ION_INTERNAL_STORAGE_H + +#include +#include +#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 = 64000; + 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 diff --git a/ion/include/ion/storage.h b/ion/include/ion/storage.h index f1a091d49..5385f4608 100644 --- a/ion/include/ion/storage.h +++ b/ion/include/ion/storage.h @@ -1,239 +1,50 @@ #ifndef ION_STORAGE_H #define ION_STORAGE_H -#include -#include +#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 = 64000; - 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 - } }; } diff --git a/ion/src/shared/internal_storage.cpp b/ion/src/shared/internal_storage.cpp new file mode 100644 index 000000000..5f12eb460 --- /dev/null +++ b/ion/src/shared/internal_storage.cpp @@ -0,0 +1,647 @@ +#include +#include +#include +#include +#include "storage.h" +#if ION_STORAGE_LOG +#include +#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; +} + +} diff --git a/ion/src/shared/storage.cpp b/ion/src/shared/storage.cpp index 200b41865..c3dd9fcc0 100644 --- a/ion/src/shared/storage.cpp +++ b/ion/src/shared/storage.cpp @@ -1,291 +1,61 @@ -#include -#include +#include #include #include -#if ION_STORAGE_LOG -#include -#endif +#include +#include 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; + return InternalStorage::availableSize() + sizeof(record_size_t) + m_trashRecord.value().size; } 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 +77,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(); + } } } diff --git a/python/port/mod/ion/file.cpp b/python/port/mod/ion/file.cpp index 721d79eee..c9eb9bc66 100644 --- a/python/port/mod/ion/file.cpp +++ b/python/port/mod/ion/file.cpp @@ -725,12 +725,12 @@ STATIC mp_obj_t file_write(mp_obj_t o_in, mp_obj_t o_s) { size_t previous_size = file->record.value().size; - // Claim avaliable space. - size_t avaliable_size = Ion::Storage::sharedStorage()->putAvailableSpaceAtEndOfRecord(file->record); + // Claim available space. + size_t available_size = Ion::Storage::sharedStorage()->putAvailableSpaceAtEndOfRecord(file->record); // Check if there is enough space left - if (file->position + len > avaliable_size) { - Ion::Storage::sharedStorage()->getAvailableSpaceFromEndOfRecord(file->record, avaliable_size - previous_size); + if (file->position + len > available_size) { + Ion::Storage::sharedStorage()->getAvailableSpaceFromEndOfRecord(file->record, available_size - previous_size); mp_raise_OSError(28); } @@ -974,12 +974,12 @@ STATIC mp_obj_t file_truncate(size_t n_args, const mp_obj_t* args) { size_t previous_size = file->record.value().size; - // Claim avaliable space. - size_t avaliable_size = Ion::Storage::sharedStorage()->putAvailableSpaceAtEndOfRecord(file->record); + // Claim available space. + size_t available_size = Ion::Storage::sharedStorage()->putAvailableSpaceAtEndOfRecord(file->record); // Check if there is enough space left - if (new_end > avaliable_size) { - Ion::Storage::sharedStorage()->getAvailableSpaceFromEndOfRecord(file->record, avaliable_size - previous_size); + if (new_end > available_size) { + Ion::Storage::sharedStorage()->getAvailableSpaceFromEndOfRecord(file->record, available_size - previous_size); mp_raise_OSError(28); } From 1c918f549cd48c7d891b03fbf543f6a8de24045d Mon Sep 17 00:00:00 2001 From: Laury Date: Sun, 13 Mar 2022 21:43:14 +0100 Subject: [PATCH 02/10] [ion] Try a fix to make compilation work --- ion/src/shared/internal_storage.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ion/src/shared/internal_storage.cpp b/ion/src/shared/internal_storage.cpp index 5f12eb460..5fc4a90d1 100644 --- a/ion/src/shared/internal_storage.cpp +++ b/ion/src/shared/internal_storage.cpp @@ -2,9 +2,9 @@ #include #include #include -#include "storage.h" +#include #if ION_STORAGE_LOG -#include +#include #endif namespace Ion { From 3740a93a9fac2bb465709fd7bef78c190d9819c9 Mon Sep 17 00:00:00 2001 From: Laury Date: Sat, 19 Mar 2022 17:59:07 +0100 Subject: [PATCH 03/10] [ion] Fixed CI --- ion/src/shared/storage.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/ion/src/shared/storage.cpp b/ion/src/shared/storage.cpp index c3dd9fcc0..50a8a4c70 100644 --- a/ion/src/shared/storage.cpp +++ b/ion/src/shared/storage.cpp @@ -14,8 +14,14 @@ Storage * Storage::sharedStorage() { } size_t Storage::availableSize() { - if (m_trashRecord != NULL) { - return InternalStorage::availableSize() + 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 InternalStorage::availableSize(); } From 42343d562c7c44f12a471a00249872ac0859096a Mon Sep 17 00:00:00 2001 From: devdl11 <54149885+devdl11@users.noreply.github.com> Date: Sat, 19 Mar 2022 19:01:50 +0100 Subject: [PATCH 04/10] [ code ] Gutter improvement (#71) (#168) --- apps/code/editor_view.cpp | 71 ++++++++++++++++++++++++++++----------- apps/code/editor_view.h | 18 ++++++++-- 2 files changed, 67 insertions(+), 22 deletions(-) diff --git a/apps/code/editor_view.cpp b/apps/code/editor_view.cpp index ab327fb52..855db6ab0 100644 --- a/apps/code/editor_view.cpp +++ b/apps/code/editor_view.cpp @@ -8,6 +8,8 @@ namespace Code { /* EditorView */ +constexpr char Code::EditorView::k_eol; + EditorView::EditorView(Responder * parentResponder, App * pythonDelegate) : Responder(parentResponder), View(), @@ -27,6 +29,9 @@ void EditorView::resetSelection() { void EditorView::scrollViewDidChangeOffset(ScrollViewDataSource * scrollViewDataSource) { m_gutterView.setOffset(scrollViewDataSource->offset().y()); + if (m_gutterView.isEditorReloadNeeded()) { + redrawSubviews(); + } } View * EditorView::subviewAtIndex(int index) { @@ -43,7 +48,7 @@ void EditorView::didBecomeFirstResponder() { void EditorView::layoutSubviews(bool force) { m_gutterView.setOffset(0); - KDCoordinate gutterWidth = m_gutterView.minimalSizeForOptimalDisplay().width(); + KDCoordinate gutterWidth = m_gutterView.widthComputed().width(); m_gutterView.setFrame(KDRect(0, 0, gutterWidth, bounds().height()), force); m_textArea.setFrame(KDRect( @@ -52,6 +57,19 @@ void EditorView::layoutSubviews(bool force) { bounds().width()-gutterWidth, bounds().height()), force); + m_gutterView.loadMaxDigits(); +} + +void EditorView::redrawSubviews() { + KDCoordinate gutterWidth = m_gutterView.widthComputed().width(); + m_gutterView.setFrame(KDRect(0, 0, gutterWidth, bounds().height()), true); + m_textArea.setFrame(KDRect( + gutterWidth, + 0, + bounds().width()-gutterWidth, + bounds().height()), + true); + markRectAsDirty(bounds()); } /* EditorView::GutterView */ @@ -67,42 +85,57 @@ 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 lineNumber[m_digits]; int numberOfLines = bounds().height() / glyphSize.height() + 1; for (int i=0; i= 10) { - line.serialize(lineNumber, k_lineNumberCharLength); - } else { - // Add a leading "0" - lineNumber[0] = '0'; - line.serialize(lineNumber + 1, k_lineNumberCharLength - 1); + + int lineDigits = getDigits(lineNumberValue); + + for (int j=0; j < (m_digits - lineDigits - 1); j++) { + lineNumber[j] = '0'; } - KDCoordinate leftPadding = (2 - strlen(lineNumber)) * glyphSize.width(); + + line.serialize(lineNumber + (m_digits-lineDigits - 1), lineDigits + 1); + + KDCoordinate leftPadding = (m_digits - strlen(lineNumber) - 1) * glyphSize.width(); ctx->drawString( - lineNumber, - KDPoint(k_margin + leftPadding, i*glyphSize.height() - firstLinePixelOffset), - m_font, - textColor, - backgroundColor + lineNumber, + KDPoint(k_margin + leftPadding, i*glyphSize.height() - firstLinePixelOffset), + m_font, + textColor, + backgroundColor ); } } +void EditorView::GutterView::loadMaxDigits() { + m_digits = getDigits((bounds().height() / m_font->glyphSize().height() + 1) + (m_offset / m_font->glyphSize().height())) + 1; +} + void EditorView::GutterView::setOffset(KDCoordinate offset) { if (m_offset == offset) { return; } m_offset = offset; + m_previousDigits = m_digits; + loadMaxDigits(); markRectAsDirty(bounds()); } +KDSize EditorView::GutterView::widthComputed() { + return KDSize(2 * k_margin + (m_digits - 1) * m_font->glyphSize().width(), 0); +} -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::getDigits(int value) { + int digits = 0; + while (value >= pow(10, digits)) {digits++;} + return digits; +} + +bool EditorView::GutterView::isEditorReloadNeeded() { + return m_previousDigits != m_digits; } } diff --git a/apps/code/editor_view.h b/apps/code/editor_view.h index 547f7340b..55ae800df 100644 --- a/apps/code/editor_view.h +++ b/apps/code/editor_view.h @@ -8,6 +8,8 @@ namespace Code { class EditorView : public Responder, public View, public ScrollViewDelegate { public: + static constexpr char k_eol = '\n'; + EditorView(Responder * parentResponder, App * pythonDelegate); PythonTextArea::AutocompletionType autocompletionType(const char ** autocompletionBeginning, const char ** autocompletionEnd) const { return m_textArea.autocompletionType(nullptr, autocompletionBeginning, autocompletionEnd); } bool isAutocompleting() const; @@ -29,6 +31,7 @@ public: void unloadSyntaxHighlighter() { m_textArea.unloadSyntaxHighlighter(); }; void scrollViewDidChangeOffset(ScrollViewDataSource * scrollViewDataSource) override; void didBecomeFirstResponder() override; + void redrawSubviews(); private: int numberOfSubviews() const override { return 2; } View * subviewAtIndex(int index) override; @@ -36,15 +39,24 @@ 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_digits(3), m_previousDigits(0) {} + void drawRect(KDContext * ctx, KDRect rect) const override; void setOffset(KDCoordinate offset); - KDSize minimalSizeForOptimalDisplay() const override; + + KDSize widthComputed(); + void loadMaxDigits(); + bool isEditorReloadNeeded(); + + static int getDigits(int value); + private: static constexpr KDCoordinate k_margin = 2; - static constexpr int k_lineNumberCharLength = 3; + const KDFont * m_font; KDCoordinate m_offset; + int m_digits; + int m_previousDigits; }; PythonTextArea m_textArea; From 97a168052bf984f6813a78dc9f7ce5fde097a05b Mon Sep 17 00:00:00 2001 From: Laury Date: Sat, 19 Mar 2022 23:39:44 +0100 Subject: [PATCH 05/10] [code] Improved code quality in gutter view resize --- apps/code/editor_view.cpp | 87 ++++++++++++++++++--------------------- apps/code/editor_view.h | 19 ++++----- 2 files changed, 46 insertions(+), 60 deletions(-) diff --git a/apps/code/editor_view.cpp b/apps/code/editor_view.cpp index 855db6ab0..1e3c34af9 100644 --- a/apps/code/editor_view.cpp +++ b/apps/code/editor_view.cpp @@ -8,8 +8,6 @@ namespace Code { /* EditorView */ -constexpr char Code::EditorView::k_eol; - EditorView::EditorView(Responder * parentResponder, App * pythonDelegate) : Responder(parentResponder), View(), @@ -28,9 +26,8 @@ void EditorView::resetSelection() { } void EditorView::scrollViewDidChangeOffset(ScrollViewDataSource * scrollViewDataSource) { - m_gutterView.setOffset(scrollViewDataSource->offset().y()); - if (m_gutterView.isEditorReloadNeeded()) { - redrawSubviews(); + if (m_gutterView.setOffsetAndNeedResize(scrollViewDataSource->offset().y())) { + internalLayoutSubviews(true); } } @@ -47,8 +44,12 @@ void EditorView::didBecomeFirstResponder() { } void EditorView::layoutSubviews(bool force) { - m_gutterView.setOffset(0); - KDCoordinate gutterWidth = m_gutterView.widthComputed().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( @@ -57,19 +58,6 @@ void EditorView::layoutSubviews(bool force) { bounds().width()-gutterWidth, bounds().height()), force); - m_gutterView.loadMaxDigits(); -} - -void EditorView::redrawSubviews() { - KDCoordinate gutterWidth = m_gutterView.widthComputed().width(); - m_gutterView.setFrame(KDRect(0, 0, gutterWidth, bounds().height()), true); - m_textArea.setFrame(KDRect( - gutterWidth, - 0, - bounds().width()-gutterWidth, - bounds().height()), - true); - markRectAsDirty(bounds()); } /* EditorView::GutterView */ @@ -85,57 +73,60 @@ void EditorView::GutterView::drawRect(KDContext * ctx, KDRect rect) const { KDCoordinate firstLine = m_offset / glyphSize.height(); KDCoordinate firstLinePixelOffset = m_offset - firstLine * glyphSize.height(); - char lineNumber[m_digits]; + char lineNumberBuffer[m_numberOfDigits + 1]; int numberOfLines = bounds().height() / glyphSize.height() + 1; for (int i=0; idrawString( - lineNumber, - KDPoint(k_margin + leftPadding, i*glyphSize.height() - firstLinePixelOffset), - m_font, - textColor, - backgroundColor + lineNumberBuffer, + KDPoint(k_margin, i*glyphSize.height() - firstLinePixelOffset), + m_font, + textColor, + backgroundColor ); } } -void EditorView::GutterView::loadMaxDigits() { - m_digits = getDigits((bounds().height() / m_font->glyphSize().height() + 1) + (m_offset / m_font->glyphSize().height())) + 1; -} - -void EditorView::GutterView::setOffset(KDCoordinate offset) { +bool EditorView::GutterView::setOffsetAndNeedResize(KDCoordinate offset) { if (m_offset == offset) { - return; + return false; } m_offset = offset; - m_previousDigits = m_digits; - loadMaxDigits(); + + int numberOfDigits = computeMaxNumberOfDigits(); + if (numberOfDigits != m_numberOfDigits) { + m_numberOfDigits = numberOfDigits; + return true; + } + markRectAsDirty(bounds()); + return false; } -KDSize EditorView::GutterView::widthComputed() { - return KDSize(2 * k_margin + (m_digits - 1) * m_font->glyphSize().width(), 0); +int EditorView::GutterView::computeWidth() { + return 2 * k_margin + (m_numberOfDigits) * m_font->glyphSize().width(); } -int EditorView::GutterView::getDigits(int value) { - int digits = 0; - while (value >= pow(10, digits)) {digits++;} +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; } -bool EditorView::GutterView::isEditorReloadNeeded() { - return m_previousDigits != m_digits; -} - } diff --git a/apps/code/editor_view.h b/apps/code/editor_view.h index 55ae800df..6c91fdde6 100644 --- a/apps/code/editor_view.h +++ b/apps/code/editor_view.h @@ -8,8 +8,6 @@ namespace Code { class EditorView : public Responder, public View, public ScrollViewDelegate { public: - static constexpr char k_eol = '\n'; - EditorView(Responder * parentResponder, App * pythonDelegate); PythonTextArea::AutocompletionType autocompletionType(const char ** autocompletionBeginning, const char ** autocompletionEnd) const { return m_textArea.autocompletionType(nullptr, autocompletionBeginning, autocompletionEnd); } bool isAutocompleting() const; @@ -31,7 +29,7 @@ public: void unloadSyntaxHighlighter() { m_textArea.unloadSyntaxHighlighter(); }; void scrollViewDidChangeOffset(ScrollViewDataSource * scrollViewDataSource) override; void didBecomeFirstResponder() override; - void redrawSubviews(); + void internalLayoutSubviews(bool force); private: int numberOfSubviews() const override { return 2; } View * subviewAtIndex(int index) override; @@ -39,24 +37,21 @@ private: class GutterView : public View { public: - GutterView(const KDFont * font) : View(), m_font(font), m_offset(0), m_digits(3), m_previousDigits(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); + bool setOffsetAndNeedResize(KDCoordinate offset); // Return true if the gutter view need to be resized - KDSize widthComputed(); - void loadMaxDigits(); - bool isEditorReloadNeeded(); - - static int getDigits(int value); + int computeWidth(); + int computeMaxNumberOfDigits(); + static int computeNumberOfDigitsFor(int value); private: static constexpr KDCoordinate k_margin = 2; const KDFont * m_font; KDCoordinate m_offset; - int m_digits; - int m_previousDigits; + int m_numberOfDigits; }; PythonTextArea m_textArea; From c92c4d8383747b0a6ece332cdd4c4cef4d516e4f Mon Sep 17 00:00:00 2001 From: Yaya-Cout <67095734+Yaya-Cout@users.noreply.github.com> Date: Sun, 20 Mar 2022 16:08:39 +0100 Subject: [PATCH 06/10] [apps/reader] Add slanted arrows, \in, \cdot, \cdots and \ldots (#184) --- apps/reader/tex_parser.cpp | 50 ++++++++++++++++-------------- kandinsky/fonts/code_points.h | 7 +++++ kandinsky/include/kandinsky/font.h | 2 +- 3 files changed, 34 insertions(+), 25 deletions(-) diff --git a/apps/reader/tex_parser.cpp b/apps/reader/tex_parser.cpp index fe105176d..1d6b4e87e 100644 --- a/apps/reader/tex_parser.cpp +++ b/apps/reader/tex_parser.cpp @@ -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); diff --git a/kandinsky/fonts/code_points.h b/kandinsky/fonts/code_points.h index ec011e91a..5d57021ca 100644 --- a/kandinsky/fonts/code_points.h +++ b/kandinsky/fonts/code_points.h @@ -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, // � // REPLACEMENT CHARACTER 0x1d422, // 𝐢 // MATHEMATICAL BOLD SMALL I" }; diff --git a/kandinsky/include/kandinsky/font.h b/kandinsky/include/kandinsky/font.h index 2b7921cce..f1bbf7ec9 100644 --- a/kandinsky/include/kandinsky/font.h +++ b/kandinsky/include/kandinsky/font.h @@ -61,7 +61,7 @@ public: CodePoint m_codePoint; GlyphIndex m_glyphIndex; }; - static constexpr GlyphIndex IndexForReplacementCharacterCodePoint = 190; + static constexpr GlyphIndex IndexForReplacementCharacterCodePoint = 197; GlyphIndex indexForCodePoint(CodePoint c) const; void setGlyphGrayscalesForCodePoint(CodePoint codePoint, GlyphBuffer * glyphBuffer) const; From 841ac7d5f4aa0b305be5a23d9d14d2a6ae521f01 Mon Sep 17 00:00:00 2001 From: Assim ZEMOUCHI Date: Sun, 20 Mar 2022 16:09:02 +0100 Subject: [PATCH 07/10] [ion] Fix win11 build for n0110 (#182) (#183) --- ion/src/device/n0110/flash.ld | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ion/src/device/n0110/flash.ld b/ion/src/device/n0110/flash.ld index e66cbbac1..dccce34bc 100644 --- a/ion/src/device/n0110/flash.ld +++ b/ion/src/device/n0110/flash.ld @@ -236,6 +236,8 @@ SECTIONS { . = ALIGN(4); *(.rodata._ZN3Ion6Device13ExternalFlash*) /* 'start' dependencies */ + *(.rodata._ZN3Ion6Device8Keyboard6ConfigL10ColumnGPIOE*) + *(.rodata._ZN3Ion6Device8Keyboard6ConfigL7RowGPIOE*) *(.rodata._ZN3Ion6Device4RegsL5GPIOAE) *(.rodata._ZN3Ion6Device4RegsL5GPIOBE) *(.rodata._ZN3Ion6Device3LED6ConfigL7RGBPinsE) From 865bacf89a347112defb4a71454db5ae26c40778 Mon Sep 17 00:00:00 2001 From: Yaya-Cout <67095734+Yaya-Cout@users.noreply.github.com> Date: Sun, 20 Mar 2022 16:10:54 +0100 Subject: [PATCH 08/10] [build/utilities] Add translations clean script (#179) --- Makefile | 5 + apps/code/base.universal.i18n | 1 - apps/code/catalog.de.i18n | 3 - apps/code/catalog.en.i18n | 3 - apps/code/catalog.es.i18n | 3 - apps/code/catalog.fr.i18n | 3 - apps/code/catalog.hu.i18n | 423 +++++----- apps/code/catalog.it.i18n | 3 - apps/code/catalog.nl.i18n | 3 - apps/code/catalog.pt.i18n | 3 - apps/code/catalog.universal.i18n | 54 -- apps/sequence/base.de.i18n | 1 - apps/sequence/base.en.i18n | 1 - apps/sequence/base.es.i18n | 1 - apps/sequence/base.fr.i18n | 1 - apps/sequence/base.hu.i18n | 43 +- apps/sequence/base.it.i18n | 1 - apps/sequence/base.nl.i18n | 1 - apps/sequence/base.pt.i18n | 1 - apps/settings/base.de.i18n | 1 - apps/settings/base.en.i18n | 1 - apps/settings/base.es.i18n | 1 - apps/settings/base.fr.i18n | 1 - apps/settings/base.hu.i18n | 163 ++-- apps/settings/base.it.i18n | 1 - apps/settings/base.nl.i18n | 1 - apps/settings/base.pt.i18n | 1 - apps/shared.de.i18n | 10 - apps/shared.en.i18n | 10 - apps/shared.es.i18n | 10 - apps/shared.fr.i18n | 10 - apps/shared.hu.i18n | 192 +++-- apps/shared.it.i18n | 10 - apps/shared.nl.i18n | 10 - apps/shared.pt.i18n | 10 - apps/shared.universal.i18n | 3 - apps/statistics/base.de.i18n | 1 - apps/statistics/base.en.i18n | 1 - apps/statistics/base.es.i18n | 3 +- apps/statistics/base.fr.i18n | 1 - apps/statistics/base.hu.i18n | 53 +- apps/statistics/base.it.i18n | 3 +- apps/statistics/base.nl.i18n | 3 +- apps/statistics/base.pt.i18n | 3 +- apps/toolbox.de.i18n | 7 - apps/toolbox.en.i18n | 7 - apps/toolbox.es.i18n | 7 - apps/toolbox.fr.i18n | 7 - apps/toolbox.hu.i18n | 1031 ++++++++++++------------- apps/toolbox.it.i18n | 7 - apps/toolbox.nl.i18n | 7 - apps/toolbox.pt.i18n | 7 - apps/usb/base.de.i18n | 2 - apps/usb/base.en.i18n | 2 - apps/usb/base.es.i18n | 2 - apps/usb/base.fr.i18n | 2 - apps/usb/base.hu.i18n | 26 +- apps/usb/base.it.i18n | 2 - apps/usb/base.nl.i18n | 2 - apps/usb/base.pt.i18n | 2 - build/utilities/translations_clean.py | 363 +++++++++ 61 files changed, 1325 insertions(+), 1215 deletions(-) create mode 100644 build/utilities/translations_clean.py diff --git a/Makefile b/Makefile index 1a424b3ef..fb08d34d4 100644 --- a/Makefile +++ b/Makefile @@ -214,3 +214,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 diff --git a/apps/code/base.universal.i18n b/apps/code/base.universal.i18n index dbbf69f5a..57acbc2ec 100644 --- a/apps/code/base.universal.i18n +++ b/apps/code/base.universal.i18n @@ -1,3 +1,2 @@ CodeAppCapital = "PYTHON" ConsolePrompt = ">>> " -ScriptParameters = "..." diff --git a/apps/code/catalog.de.i18n b/apps/code/catalog.de.i18n index 15492dbd9..bb4c19947 100644 --- a/apps/code/catalog.de.i18n +++ b/apps/code/catalog.de.i18n @@ -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?" diff --git a/apps/code/catalog.en.i18n b/apps/code/catalog.en.i18n index 298b16d2b..7241ff9b1 100644 --- a/apps/code/catalog.en.i18n +++ b/apps/code/catalog.en.i18n @@ -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" diff --git a/apps/code/catalog.es.i18n b/apps/code/catalog.es.i18n index c2209a3f5..4bc9eb2dc 100644 --- a/apps/code/catalog.es.i18n +++ b/apps/code/catalog.es.i18n @@ -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" diff --git a/apps/code/catalog.fr.i18n b/apps/code/catalog.fr.i18n index 5b2b41166..c43c9a2c2 100644 --- a/apps/code/catalog.fr.i18n +++ b/apps/code/catalog.fr.i18n @@ -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é" diff --git a/apps/code/catalog.hu.i18n b/apps/code/catalog.hu.i18n index 570537a6e..ad7eb410f 100644 --- a/apps/code/catalog.hu.i18n +++ b/apps/code/catalog.hu.i18n @@ -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)" diff --git a/apps/code/catalog.it.i18n b/apps/code/catalog.it.i18n index 8aa015729..9a1bae232 100644 --- a/apps/code/catalog.it.i18n +++ b/apps/code/catalog.it.i18n @@ -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" diff --git a/apps/code/catalog.nl.i18n b/apps/code/catalog.nl.i18n index 17c9f9eb7..8fe6b81e0 100644 --- a/apps/code/catalog.nl.i18n +++ b/apps/code/catalog.nl.i18n @@ -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" diff --git a/apps/code/catalog.pt.i18n b/apps/code/catalog.pt.i18n index 3243a1e0c..1a894c322 100644 --- a/apps/code/catalog.pt.i18n +++ b/apps/code/catalog.pt.i18n @@ -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" diff --git a/apps/code/catalog.universal.i18n b/apps/code/catalog.universal.i18n index 8159d966b..7da352806 100644 --- a/apps/code/catalog.universal.i18n +++ b/apps/code/catalog.universal.i18n @@ -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])" diff --git a/apps/sequence/base.de.i18n b/apps/sequence/base.de.i18n index 88f518ca9..21da2aeab 100644 --- a/apps/sequence/base.de.i18n +++ b/apps/sequence/base.de.i18n @@ -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" diff --git a/apps/sequence/base.en.i18n b/apps/sequence/base.en.i18n index e9917698c..8776d4b79 100644 --- a/apps/sequence/base.en.i18n +++ b/apps/sequence/base.en.i18n @@ -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" diff --git a/apps/sequence/base.es.i18n b/apps/sequence/base.es.i18n index 4bf2fe492..691b286b2 100644 --- a/apps/sequence/base.es.i18n +++ b/apps/sequence/base.es.i18n @@ -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" diff --git a/apps/sequence/base.fr.i18n b/apps/sequence/base.fr.i18n index 3772efb47..09d8bfa9d 100644 --- a/apps/sequence/base.fr.i18n +++ b/apps/sequence/base.fr.i18n @@ -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" diff --git a/apps/sequence/base.hu.i18n b/apps/sequence/base.hu.i18n index f98ed2366..b52a13cfa 100644 --- a/apps/sequence/base.hu.i18n +++ b/apps/sequence/base.hu.i18n @@ -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" diff --git a/apps/sequence/base.it.i18n b/apps/sequence/base.it.i18n index d9ddac4a1..3d714acfe 100644 --- a/apps/sequence/base.it.i18n +++ b/apps/sequence/base.it.i18n @@ -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" diff --git a/apps/sequence/base.nl.i18n b/apps/sequence/base.nl.i18n index 34a63d53d..178761f1d 100644 --- a/apps/sequence/base.nl.i18n +++ b/apps/sequence/base.nl.i18n @@ -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" diff --git a/apps/sequence/base.pt.i18n b/apps/sequence/base.pt.i18n index 97f6580f8..3cfbb3338 100644 --- a/apps/sequence/base.pt.i18n +++ b/apps/sequence/base.pt.i18n @@ -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" diff --git a/apps/settings/base.de.i18n b/apps/settings/base.de.i18n index 2f38be2bb..d44631a8c 100644 --- a/apps/settings/base.de.i18n +++ b/apps/settings/base.de.i18n @@ -62,7 +62,6 @@ SymbolFunction = "Ausdrucksformat " SymbolDefaultFunction = "Standardl " SymbolArgFunction = "Leer " SymbolArgDefaultFunction = "Argument " -PythonFont = "Python Schriftart" MemUse = "Speicher" DateTime = "Datum/Uhrzeit" ActivateClock = "Uhr aktivieren" diff --git a/apps/settings/base.en.i18n b/apps/settings/base.en.i18n index ebdc55abe..50707610f 100644 --- a/apps/settings/base.en.i18n +++ b/apps/settings/base.en.i18n @@ -62,7 +62,6 @@ SymbolFunction = "Expression format " SymbolDefaultFunction = "Default " SymbolArgFunction = "Empty " SymbolArgDefaultFunction = "Argument " -PythonFont = "Python Font" MemUse = "Memory" DateTime = "Date/time" ActivateClock = "Activate clock" diff --git a/apps/settings/base.es.i18n b/apps/settings/base.es.i18n index b3b8ec6e6..4d47b15e0 100644 --- a/apps/settings/base.es.i18n +++ b/apps/settings/base.es.i18n @@ -62,7 +62,6 @@ SymbolFunction = "Formato expresión " SymbolDefaultFunction = "Defecto " SymbolArgFunction = "Vacío " SymbolArgDefaultFunction = "Argumento " -PythonFont = "Fuente Python" MemUse = "Memoria" DateTime = "Fecha/Hora" ActivateClock = "Activar el reloj" diff --git a/apps/settings/base.fr.i18n b/apps/settings/base.fr.i18n index 3204ba621..e20010761 100644 --- a/apps/settings/base.fr.i18n +++ b/apps/settings/base.fr.i18n @@ -62,7 +62,6 @@ SymbolFunction = "Format expression " SymbolDefaultFunction = "Défaut " SymbolArgFunction = "Vide " SymbolArgDefaultFunction = "Arguments " -PythonFont = "Police Python" MemUse = "Mémoire" DateTime = "Date/heure" ActivateClock = "Activer horloge" diff --git a/apps/settings/base.hu.i18n b/apps/settings/base.hu.i18n index 080b7b5da..3b4f083f7 100644 --- a/apps/settings/base.hu.i18n +++ b/apps/settings/base.hu.i18n @@ -1,82 +1,81 @@ -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ö" +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" diff --git a/apps/settings/base.it.i18n b/apps/settings/base.it.i18n index ae64c22dd..a292dd0d2 100644 --- a/apps/settings/base.it.i18n +++ b/apps/settings/base.it.i18n @@ -62,7 +62,6 @@ SymbolFunction = "Expression format " SymbolDefaultFunction = "Default " SymbolArgFunction = "Empty " SymbolArgDefaultFunction = "Argument " -PythonFont = "Python Font" MemUse = "Memory" DateTime = "Date/time" ActivateClock = "Activate clock" diff --git a/apps/settings/base.nl.i18n b/apps/settings/base.nl.i18n index 6d72e3402..9baf4be17 100644 --- a/apps/settings/base.nl.i18n +++ b/apps/settings/base.nl.i18n @@ -62,7 +62,6 @@ SymbolFunction = "Expression format " SymbolDefaultFunction = "Default " SymbolArgFunction = "Empty " SymbolArgDefaultFunction = "Argument " -PythonFont = "Python Font" MemUse = "Memory" DateTime = "Date/time" ActivateClock = "Activate clock" diff --git a/apps/settings/base.pt.i18n b/apps/settings/base.pt.i18n index d1f42789c..66a432820 100644 --- a/apps/settings/base.pt.i18n +++ b/apps/settings/base.pt.i18n @@ -62,7 +62,6 @@ SymbolFunction = "Formato expressão " SymbolDefaultFunction = "Padrão " SymbolArgFunction = "Vazio " SymbolArgDefaultFunction = "Argumento " -PythonFont = "Fonte Python" MemUse = "Memória" DateTime = "Date/time" ActivateClock = "Activate clock" diff --git a/apps/shared.de.i18n b/apps/shared.de.i18n index 721941691..b89268501 100644 --- a/apps/shared.de.i18n +++ b/apps/shared.de.i18n @@ -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,9 +84,6 @@ ValuesTab = "Tabelle" Warning = "Achtung" XEnd = "X Endwert" XStart = "X Startwert" -Zoom = "Zoom" -Developers = "Entwickler" -BetaTesters = "Beta-Tester" ExamModeMode = "Modus" ExamModeModeStandard = "Standard " ExamModeModeNoSym = "Kein Symbol " diff --git a/apps/shared.en.i18n b/apps/shared.en.i18n index d61df44e1..c18e948aa 100644 --- a/apps/shared.en.i18n +++ b/apps/shared.en.i18n @@ -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,9 +84,6 @@ ValuesTab = "Table" Warning = "Warning" XEnd = "X end" XStart = "X start" -Zoom = "Zoom" -Developers = "Developers" -BetaTesters = "Beta testers" ExamModeMode = "Mode" ExamModeModeStandard = "Standard " ExamModeModeNoSym = "No sym " diff --git a/apps/shared.es.i18n b/apps/shared.es.i18n index e542571ed..800b30355 100644 --- a/apps/shared.es.i18n +++ b/apps/shared.es.i18n @@ -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,9 +84,6 @@ 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 " diff --git a/apps/shared.fr.i18n b/apps/shared.fr.i18n index 46b76202d..6bcacc18e 100644 --- a/apps/shared.fr.i18n +++ b/apps/shared.fr.i18n @@ -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,9 +84,6 @@ 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 " diff --git a/apps/shared.hu.i18n b/apps/shared.hu.i18n index 60ba0754b..b9be6807b 100644 --- a/apps/shared.hu.i18n +++ b/apps/shared.hu.i18n @@ -1,101 +1,91 @@ -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 " diff --git a/apps/shared.it.i18n b/apps/shared.it.i18n index 3322800c8..4476ed58c 100644 --- a/apps/shared.it.i18n +++ b/apps/shared.it.i18n @@ -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,9 +84,6 @@ ValuesTab = "Tabella" Warning = "Attenzione" XEnd = "X finale" XStart = "X iniziale" -Zoom = "Zoom" -Developers = "Developers" -BetaTesters = "Beta testers" ExamModeMode = "Modalità" ExamModeModeStandard = "Standard " ExamModeModeNoSym = "Nessun simbolo " diff --git a/apps/shared.nl.i18n b/apps/shared.nl.i18n index b3971aa6c..cd091b0dc 100644 --- a/apps/shared.nl.i18n +++ b/apps/shared.nl.i18n @@ -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,9 +84,6 @@ ValuesTab = "Tabel" Warning = "Waarschuwing" XEnd = "X einde" XStart = "X begin" -Zoom = "Zoom" -Developers = "Developers" -BetaTesters = "Beta testers" ExamModeMode = "Mode" ExamModeModeStandard = "Standaard " ExamModeModeNoSym = "Geen sym " diff --git a/apps/shared.pt.i18n b/apps/shared.pt.i18n index 39fa24c12..b68443df1 100644 --- a/apps/shared.pt.i18n +++ b/apps/shared.pt.i18n @@ -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,9 +84,6 @@ 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 " diff --git a/apps/shared.universal.i18n b/apps/shared.universal.i18n index d1d3fc9b5..cad61ea9b 100644 --- a/apps/shared.universal.i18n +++ b/apps/shared.universal.i18n @@ -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_Ω" diff --git a/apps/statistics/base.de.i18n b/apps/statistics/base.de.i18n index 8a84b549e..256fae301 100644 --- a/apps/statistics/base.de.i18n +++ b/apps/statistics/base.de.i18n @@ -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:" diff --git a/apps/statistics/base.en.i18n b/apps/statistics/base.en.i18n index 4bb669729..645eeb474 100644 --- a/apps/statistics/base.en.i18n +++ b/apps/statistics/base.en.i18n @@ -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:" diff --git a/apps/statistics/base.es.i18n b/apps/statistics/base.es.i18n index 648c85169..2eb0c5f5b 100644 --- a/apps/statistics/base.es.i18n +++ b/apps/statistics/base.es.i18n @@ -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" \ No newline at end of file +InterquartileRange = "Rango intercuartilo" diff --git a/apps/statistics/base.fr.i18n b/apps/statistics/base.fr.i18n index c6fbf2966..c3459bbdc 100644 --- a/apps/statistics/base.fr.i18n +++ b/apps/statistics/base.fr.i18n @@ -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:" diff --git a/apps/statistics/base.hu.i18n b/apps/statistics/base.hu.i18n index 097a28b22..82da786c6 100644 --- a/apps/statistics/base.hu.i18n +++ b/apps/statistics/base.hu.i18n @@ -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" diff --git a/apps/statistics/base.it.i18n b/apps/statistics/base.it.i18n index 2879e7e63..043fd75df 100644 --- a/apps/statistics/base.it.i18n +++ b/apps/statistics/base.it.i18n @@ -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" \ No newline at end of file +InterquartileRange = "Scarto interquartile" diff --git a/apps/statistics/base.nl.i18n b/apps/statistics/base.nl.i18n index 2e43cbc20..beee307b8 100644 --- a/apps/statistics/base.nl.i18n +++ b/apps/statistics/base.nl.i18n @@ -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" \ No newline at end of file +InterquartileRange = "Interkwartielafstand" diff --git a/apps/statistics/base.pt.i18n b/apps/statistics/base.pt.i18n index 29ac75e6e..11f5df9f1 100644 --- a/apps/statistics/base.pt.i18n +++ b/apps/statistics/base.pt.i18n @@ -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" \ No newline at end of file +InterquartileRange = "Amplitude interquartil" diff --git a/apps/toolbox.de.i18n b/apps/toolbox.de.i18n index e4a7c49e4..40c021a70 100644 --- a/apps/toolbox.de.i18n +++ b/apps/toolbox.de.i18n @@ -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" diff --git a/apps/toolbox.en.i18n b/apps/toolbox.en.i18n index e2d7dd94a..b3ff61e29 100644 --- a/apps/toolbox.en.i18n +++ b/apps/toolbox.en.i18n @@ -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" diff --git a/apps/toolbox.es.i18n b/apps/toolbox.es.i18n index 21247a271..f4f9a212c 100644 --- a/apps/toolbox.es.i18n +++ b/apps/toolbox.es.i18n @@ -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" diff --git a/apps/toolbox.fr.i18n b/apps/toolbox.fr.i18n index 4cd0db6fa..41164cd08 100644 --- a/apps/toolbox.fr.i18n +++ b/apps/toolbox.fr.i18n @@ -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" diff --git a/apps/toolbox.hu.i18n b/apps/toolbox.hu.i18n index 137c37917..79d22308a 100644 --- a/apps/toolbox.hu.i18n +++ b/apps/toolbox.hu.i18n @@ -1,519 +1,512 @@ -Unit = "Mértékegység" -UnitTimeMenu = "Idö" -UnitTimeSecondMenu = "Másodperc" -UnitTimeSecond = "Másodperc" -UnitTimeSecondMilli = "Miliszekundum" -UnitTimeSecondMicro = "Mikroszekundum" -UnitTimeSecondNano = "Nanoszekundum" -UnitTimeMinute = "Perc" -UnitTimeHour = "Óra" -UnitTimeDay = "Nap" -UnitTimeWeek = "hét" -UnitTimeMonth = "Hónap" -UnitTimeYear = "Év" -UnitDistanceMenu = "Távolság" -UnitDistanceMeterMenu = "Méter" -UnitDistanceMeterKilo = "Kilométer" -UnitDistanceMeter = "Méter" -UnitDistanceMeterMilli = "Milliméter" -UnitDistanceMeterMicro = "Mikrométer" -UnitDistanceMeterNano = "Nanométer" -UnitDistanceMeterPico = "Pikométer" -UnitDistanceImperialMenu = "Angolszász mértékegységek" -UnitDistanceInch = "Hüvelyk" -UnitDistanceFoot = "Láb" -UnitDistanceYard = "Yard" -UnitDistanceMile = "Mérföld" -UnitDistanceAstronomicalUnit = "Csillagászati egység" -UnitDistanceLightYear = "Fény év" -UnitDistanceParsec = "Parsec" -UnitMassShortTon = "Rövid tonna" -UnitMassLongTon = "Hosszú tonna" -UnitMassImperialMenu = "Angolszász mértékegységek" -UnitMassPound = "Font" -UnitMassOunce = "Uncia" -UnitMassMenu = "Tömeg" -UnitMassGramKilo = "Kilogramm" -UnitMassGram = "Gramm" -UnitMassGramMilli = "Milligramm" -UnitMassGramMicro = "Mikrogramm" -UnitMassGramNano = "Nanogramm" -UnitMassTonne = "Tonna" -UnitCurrentMenu = "Áram" -UnitCurrentAmpere = "Amper" -UnitCurrentAmpereMilli = "Milliamper" -UnitCurrentAmpereMicro = "Mikroamper" -UnitTemperatureMenu = "Hömérséklet" -UnitAmountMenu = "Az anyag mennyisége" -UnitAmountMole = "Mól" -UnitAmountMoleMilli = "Millimól" -UnitAmountMoleMicro = "Mikromól" -UnitLuminousIntensityMenu = "Fényerö" -UnitFrequencyMenu = "Frekvencia" -UnitFrequencyHertzMega = "Megahertz" -UnitForceMenu = "Erö" -UnitForceNewtonMilli = "Millinewton" -UnitPressureMenu = "Nyomás" -UnitPressurePascalHecto = "Hectopascal" -UnitPressureAtm = "Légkör" -UnitEnergyMenu = "Energia" -UnitEnergyJouleMilli = "Millijoule" -UnitEnergyElectronVoltMenu = "Electronvolt" -UnitEnergyElectronVoltMega = "Megaelectronvolt" -UnitEnergyElectronVoltKilo = "Kiloelectronvolt" -UnitEnergyElectronVolt = "Electronvolt" -UnitEnergyElectronVoltMilli = "Millielectronvolt" -UnitPowerMenu = "Teljesítmény" -UnitPowerWattMega = "Megawatt" -UnitPowerWattMilli = "Milliwatt" -UnitPowerWattMicro = "Microwatt" -UnitElectricChargeMenu = "Elektromos töltés" -UnitPotentialMenu = "Elektromos potenciál" -UnitPotentialVoltMilli = "Millivolt" -UnitPotentialVoltMicro = "Microvolt" -UnitCapacitanceMenu = "Elektromos kapacitás" -UnitCapacitanceFaradMilli = "Millifarad" -UnitCapacitanceFaradMicro = "Microfarad" -UnitResistanceMenu = "Elektromos ellenállás" -UnitConductanceMenu = "Elektromos vezetöképesség" -UnitConductanceSiemensMilli = "Millisiemens" -UnitMagneticFieldMenu = "Mágneses mezö" -InductanceMenu = "Elektromos induktivitás" -UnitSurfaceMenu = "Terület" -UnitSurfaceAcre = "Acre" -UnitSurfaceHectar = "Hektár" -UnitVolumeMenu = "Kötet" -UnitVolumeLiter = "Liter" -UnitVolumeLiterDeci = "Deciliter" -UnitVolumeLiterCenti = "Centiliter" -UnitVolumeLiterMilli = "Milliliter" -UnitVolumeTeaspoon = "Teáskanál" -UnitVolumeTablespoon = "evőkanál" -UnitVolumeFluidOunce = "Folyadék uncia" -UnitVolumeCup = "Kupa" -UnitVolumePint = "Pint" -UnitVolumeQuart = "Quart" -UnitVolumeGallon = "Gallon" -UnitMetricMenu = "Metrikus" -UnitImperialMenu = "Birodalmi" -Toolbox = "Eszköztár" -AbsoluteValue = "Abszolút érték" -NthRoot = "n-gyökér" -BasedLogarithm = "Logaritmus az alap" -Calculation = "Számítás" -ComplexNumber = "Komplex számok" -Combinatorics = "Kombinatorika" -Arithmetic = "számtani" -Matrices = "Mátrix" -NewMatrix = "Új mátrix" -Identity = "n méretü azonosító mátrix" -Lists = "Lista" -HyperbolicTrigonometry = "Hiperbolikus trigonometria" -Fluctuation = "Jósolt intervallum" -InfinityMessage = "Végtelen" -DerivateNumber = "Származékos" -Integral = "Integral" -Sum = "Összeg" -Product = "Termék" -ComplexAbsoluteValue = "Abszolút érték" -Argument = "érv" -RealPart = "Igazi rész" -ImaginaryPart = "Képzeletbeli rész" -Conjugate = "Konjugátum" -Combination = "Kombináció" -Permutation = "Permutáció" -GreatCommonDivisor = "GCD" -LeastCommonMultiple = "LCM" -Remainder = "P maradékos osztás q-val" -Quotient = "P hányados osztás q-val" -Inverse = "Inverz" -Determinant = "determináns" -Transpose = "Átültetés" -Trace = "Trace" -Dimension = "Méret" -RowEchelonForm = "Sor echelon forma" -ReducedRowEchelonForm = "Csökkentett sorú echelon forma" -Vectors = "Vektorok" -Dot = "Pont termék" -Cross = "Kereszt termék" -NormVector = "Norm" -Sort = "Növekvö sorrend" -InvSort = "Csökkenö rendezés" -Maximum = "Maximum" -Minimum = "Minimum" -Floor = "Emelet" -FracPart = "Frakciós rész" -Ceiling = "Plafon" -Rounding = "N számjegyre kerekítés" -HyperbolicCosine = "Hiperbolikus koszinusz" -HyperbolicSine = "Hiperbolikus szinusz" -HyperbolicTangent = "Hiperbolikus érintö" -InverseHyperbolicCosine = "Inverz hiperbolikus koszinusz" -InverseHyperbolicSine = "Inverz hiperbolikus szinusz" -InverseHyperbolicTangent = "Inverz hiperbolikus érintö" -Prediction95 = "Jóslási intervallum 95%" -Prediction = "Egyszerü elörejelzési intervallum" -Confidence = "Bizalmi intervallum" -RandomAndApproximation = "Véletlen és közelítés" -RandomFloat = "Lebegöpontos szám [0,1-ben [" -RandomInteger = "Véletlen egész szám [a, b] -ben" -PrimeFactorDecomposition = "Egész szám tényezö" -NormCDF = "P (X 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() From 8ac969d772fc6cad691d0a04438a25c84843634b Mon Sep 17 00:00:00 2001 From: Yaya-Cout <67095734+Yaya-Cout@users.noreply.github.com> Date: Tue, 22 Mar 2022 17:59:52 +0100 Subject: [PATCH 09/10] [Feature] Backlight settings (#137) * Added backlight settings * Changed location of the brightness setting * Fix row size of brightness settings * [apps/settings/brightness] Update translations * Fix dimmer * Update translations * [apps/settings] Add dimmer duration setting * [apps/settings] Ensure of the brightness level is greater than the dimmed brightness level * Make transition smooth * Removed transition time setting I personally think that this setting is completely useless except if you absolutely want a transition that is not smooth, which is weird. * Moved everything related to brightness in one submenu * Some refactoring * Update defaults * Removed unnecessary translation * [apps/settings] Fix Shift + Minus/Plus in settings * Apply suggestions from code review * [apps/shared] Remove a think that I don't know what it is * Apply review suggestions Co-authored-by: Joachim LF Co-authored-by: lolocomotive --- apps/apps_container.cpp | 5 +- apps/backlight_dimming_timer.cpp | 43 ++---- apps/backlight_dimming_timer.h | 11 -- apps/global_preferences.cpp | 21 ++- apps/global_preferences.h | 12 ++ apps/settings/Makefile | 1 + apps/settings/base.de.i18n | 5 + apps/settings/base.en.i18n | 5 + apps/settings/base.es.i18n | 5 + apps/settings/base.fr.i18n | 5 + apps/settings/base.hu.i18n | 5 + apps/settings/base.it.i18n | 5 + apps/settings/base.nl.i18n | 5 + apps/settings/base.pt.i18n | 5 + apps/settings/main_controller.cpp | 35 +---- apps/settings/main_controller.h | 6 +- apps/settings/main_controller_prompt_beta.cpp | 2 +- apps/settings/main_controller_prompt_none.cpp | 2 +- .../main_controller_prompt_update.cpp | 4 +- .../sub_menu/brightness_controller.cpp | 142 ++++++++++++++++++ .../settings/sub_menu/brightness_controller.h | 33 ++++ apps/suspend_timer.cpp | 2 +- apps/suspend_timer.h | 1 - escher/include/escher/timer.h | 2 +- escher/src/timer.cpp | 5 +- ion/include/ion/backlight.h | 1 - 26 files changed, 288 insertions(+), 80 deletions(-) create mode 100644 apps/settings/sub_menu/brightness_controller.cpp create mode 100644 apps/settings/sub_menu/brightness_controller.h diff --git a/apps/apps_container.cpp b/apps/apps_container.cpp index 9423684e4..1bb917ddc 100644 --- a/apps/apps_container.cpp +++ b/apps/apps_container.cpp @@ -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(); } diff --git a/apps/backlight_dimming_timer.cpp b/apps/backlight_dimming_timer.cpp index 0d98d2749..a86c29c00 100644 --- a/apps/backlight_dimming_timer.cpp +++ b/apps/backlight_dimming_timer.cpp @@ -1,39 +1,26 @@ #include "backlight_dimming_timer.h" #include "global_preferences.h" +#include +#include +#include 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; -} diff --git a/apps/backlight_dimming_timer.h b/apps/backlight_dimming_timer.h index 1502ea2dc..192591370 100644 --- a/apps/backlight_dimming_timer.h +++ b/apps/backlight_dimming_timer.h @@ -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 diff --git a/apps/global_preferences.cpp b/apps/global_preferences.cpp index 938cff861..c0eac31c8 100644 --- a/apps/global_preferences.cpp +++ b/apps/global_preferences.cpp @@ -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; +} diff --git a/apps/global_preferences.h b/apps/global_preferences.h index bcfa324ea..f092fdaa0 100644 --- a/apps/global_preferences.h +++ b/apps/global_preferences.h @@ -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; }; diff --git a/apps/settings/Makefile b/apps/settings/Makefile index 9823f80dd..c806527cb 100644 --- a/apps/settings/Makefile +++ b/apps/settings/Makefile @@ -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)" diff --git a/apps/settings/base.de.i18n b/apps/settings/base.de.i18n index d44631a8c..225fb46bf 100644 --- a/apps/settings/base.de.i18n +++ b/apps/settings/base.de.i18n @@ -32,6 +32,7 @@ Real = "Reell " Cartesian = "Kartesisch " Polar = "Polar " Brightness = "Helligkeit" +BrightnessSettings = "Helligkeitseinstellungen" SoftwareVersion = "Epsilon version" UpsilonVersion = "Upsilon version" OmegaVersion = "Omega version" @@ -79,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" diff --git a/apps/settings/base.en.i18n b/apps/settings/base.en.i18n index 50707610f..427eed03c 100644 --- a/apps/settings/base.en.i18n +++ b/apps/settings/base.en.i18n @@ -32,6 +32,7 @@ Real = "Real " Cartesian = "Cartesian " Polar = "Polar " Brightness = "Brightness" +BrightnessSettings = "Brightness settings" SoftwareVersion = "Epsilon version" UpsilonVersion = "Upsilon version" OmegaVersion = "Omega version" @@ -79,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" diff --git a/apps/settings/base.es.i18n b/apps/settings/base.es.i18n index 4d47b15e0..b5723e5a7 100644 --- a/apps/settings/base.es.i18n +++ b/apps/settings/base.es.i18n @@ -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" @@ -79,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" diff --git a/apps/settings/base.fr.i18n b/apps/settings/base.fr.i18n index e20010761..c8131e975 100644 --- a/apps/settings/base.fr.i18n +++ b/apps/settings/base.fr.i18n @@ -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" @@ -79,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" diff --git a/apps/settings/base.hu.i18n b/apps/settings/base.hu.i18n index 3b4f083f7..4d5485cda 100644 --- a/apps/settings/base.hu.i18n +++ b/apps/settings/base.hu.i18n @@ -32,6 +32,7 @@ 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ó" @@ -79,3 +80,7 @@ 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" diff --git a/apps/settings/base.it.i18n b/apps/settings/base.it.i18n index a292dd0d2..74701f626 100644 --- a/apps/settings/base.it.i18n +++ b/apps/settings/base.it.i18n @@ -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" @@ -79,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" diff --git a/apps/settings/base.nl.i18n b/apps/settings/base.nl.i18n index 9baf4be17..b393b653b 100644 --- a/apps/settings/base.nl.i18n +++ b/apps/settings/base.nl.i18n @@ -32,6 +32,7 @@ Real = "Reëel " Cartesian = "Cartesisch " Polar = "Polair " Brightness = "Helderheid" +BrightnessSettings = "Helderheidsinstellingen" SoftwareVersion = "Epsilon version" UpsilonVersion = "Upsilon version" OmegaVersion = "Omega version" @@ -79,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" diff --git a/apps/settings/base.pt.i18n b/apps/settings/base.pt.i18n index 66a432820..c11a54a16 100644 --- a/apps/settings/base.pt.i18n +++ b/apps/settings/base.pt.i18n @@ -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" @@ -79,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" diff --git a/apps/settings/main_controller.cpp b/apps/settings/main_controller.cpp index 1b2e48468..71f7a5a34 100644 --- a/apps/settings/main_controller.cpp +++ b/apps/settings/main_controller.cpp @@ -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) { diff --git a/apps/settings/main_controller.h b/apps/settings/main_controller.h index 28c5b07d7..5a721e0c4 100644 --- a/apps/settings/main_controller.h +++ b/apps/settings/main_controller.h @@ -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; diff --git a/apps/settings/main_controller_prompt_beta.cpp b/apps/settings/main_controller_prompt_beta.cpp index 80b3e1459..90df4b897 100644 --- a/apps/settings/main_controller_prompt_beta.cpp +++ b/apps/settings/main_controller_prompt_beta.cpp @@ -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), diff --git a/apps/settings/main_controller_prompt_none.cpp b/apps/settings/main_controller_prompt_none.cpp index d0b2727c5..9dc5d45a6 100644 --- a/apps/settings/main_controller_prompt_none.cpp +++ b/apps/settings/main_controller_prompt_none.cpp @@ -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), diff --git a/apps/settings/main_controller_prompt_update.cpp b/apps/settings/main_controller_prompt_update.cpp index e028803ef..48c5b5012 100644 --- a/apps/settings/main_controller_prompt_update.cpp +++ b/apps/settings/main_controller_prompt_update.cpp @@ -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), diff --git a/apps/settings/sub_menu/brightness_controller.cpp b/apps/settings/sub_menu/brightness_controller.cpp new file mode 100644 index 000000000..9af1f4215 --- /dev/null +++ b/apps/settings/sub_menu/brightness_controller.cpp @@ -0,0 +1,142 @@ +#include "brightness_controller.h" +#include "../../global_preferences.h" +#include "../../apps_container.h" +#include "../../shared/poincare_helpers.h" +#include +#include +#include "../app.h" +#include +#include + +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; +} + +} diff --git a/apps/settings/sub_menu/brightness_controller.h b/apps/settings/sub_menu/brightness_controller.h new file mode 100644 index 000000000..a36a39a32 --- /dev/null +++ b/apps/settings/sub_menu/brightness_controller.h @@ -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 diff --git a/apps/suspend_timer.cpp b/apps/suspend_timer.cpp index 34562d819..b21c1d6b3 100644 --- a/apps/suspend_timer.cpp +++ b/apps/suspend_timer.cpp @@ -2,7 +2,7 @@ #include "apps_container.h" SuspendTimer::SuspendTimer() : - Timer(k_idleBeforeSuspendDuration/Timer::TickDuration) + Timer(GlobalPreferences::sharedGlobalPreferences()->idleBeforeSuspendSeconds()*1000/Timer::TickDuration) { } diff --git a/apps/suspend_timer.h b/apps/suspend_timer.h index 0a7b735d6..8125ca855 100644 --- a/apps/suspend_timer.h +++ b/apps/suspend_timer.h @@ -7,7 +7,6 @@ class SuspendTimer : public Timer { public: SuspendTimer(); private: - constexpr static int k_idleBeforeSuspendDuration = 5*60*1000; // In miliseconds bool fire() override; }; diff --git a/escher/include/escher/timer.h b/escher/include/escher/timer.h index 3a7e2a7ec..94ed476c4 100644 --- a/escher/include/escher/timer.h +++ b/escher/include/escher/timer.h @@ -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; diff --git a/escher/src/timer.cpp b/escher/src/timer.cpp index 0e9f5a5ea..742634fbf 100644 --- a/escher/src/timer.cpp +++ b/escher/src/timer.cpp @@ -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; } diff --git a/ion/include/ion/backlight.h b/ion/include/ion/backlight.h index 89a19687c..cd69ee888 100644 --- a/ion/include/ion/backlight.h +++ b/ion/include/ion/backlight.h @@ -12,7 +12,6 @@ bool isInitialized(); void shutdown(); void setBrightness(uint8_t b); uint8_t brightness(); -const int NumberOfStepsPerShortcut = 4; } } From 3b293c822a14a6e82951d469de6bcb6ea37cb958 Mon Sep 17 00:00:00 2001 From: Yaya-Cout <67095734+Yaya-Cout@users.noreply.github.com> Date: Wed, 23 Mar 2022 08:36:23 +0100 Subject: [PATCH 10/10] [apps/graph] Added a color menu in graph and list (#189) * Revert "[github/workflows] Update Metrics to remove NumWorksBot" This reverts commit 110f33312264861427280414798d8170a4468488. * Added a color menu in graph and list * Fixed color select display issue and build issue * Changed color_cell to a circle * Revert "Changed color_cell to a circle" This reverts commit 28dddb42af18ace8599615b33e14b5dd23bdeff2. * Color_cell with mask * Fixed build issue * Color selection : Added right handle and color name display in menu * Fixed constexpr static colorMask * Changed font in color_parameter_controller * Fix building without debug * Re-Fix building without debug * Update colors Co-authored-by: Hugo Saint-Vignes Co-authored-by: Joachim LF --- apps/graph/list/list_parameter_controller.cpp | 2 +- .../list/list_parameter_controller.cpp | 22 +---- .../sequence/list/list_parameter_controller.h | 4 - apps/shared.de.i18n | 7 ++ apps/shared.en.i18n | 7 ++ apps/shared.es.i18n | 7 ++ apps/shared.fr.i18n | 7 ++ apps/shared.hu.i18n | 7 ++ apps/shared.it.i18n | 7 ++ apps/shared.nl.i18n | 7 ++ apps/shared.pt.i18n | 7 ++ apps/shared/Makefile | 2 + apps/shared/color_cell.cpp | 51 +++++++++++ apps/shared/color_cell.h | 42 +++++++++ apps/shared/color_parameter_controller.cpp | 86 +++++++++++++++++++ apps/shared/color_parameter_controller.h | 44 ++++++++++ apps/shared/function.cpp | 4 + apps/shared/function.h | 2 + apps/shared/list_parameter_controller.cpp | 39 +++++---- apps/shared/list_parameter_controller.h | 10 +-- 20 files changed, 312 insertions(+), 52 deletions(-) create mode 100644 apps/shared/color_cell.cpp create mode 100644 apps/shared/color_cell.h create mode 100644 apps/shared/color_parameter_controller.cpp create mode 100644 apps/shared/color_parameter_controller.h diff --git a/apps/graph/list/list_parameter_controller.cpp b/apps/graph/list/list_parameter_controller.cpp index 29b7bbdef..01d266db2 100644 --- a/apps/graph/list/list_parameter_controller.cpp +++ b/apps/graph/list/list_parameter_controller.cpp @@ -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); } diff --git a/apps/sequence/list/list_parameter_controller.cpp b/apps/sequence/list/list_parameter_controller.cpp index 9058083e3..2ac1397cd 100644 --- a/apps/sequence/list/list_parameter_controller.cpp +++ b/apps/sequence/list/list_parameter_controller.cpp @@ -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); } diff --git a/apps/sequence/list/list_parameter_controller.h b/apps/sequence/list/list_parameter_controller.h index 911630a0c..06166e8b0 100644 --- a/apps/sequence/list/list_parameter_controller.h +++ b/apps/sequence/list/list_parameter_controller.h @@ -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(function().pointer()); } bool hasInitialRankRow() const; diff --git a/apps/shared.de.i18n b/apps/shared.de.i18n index b89268501..1e61ff9f5 100644 --- a/apps/shared.de.i18n +++ b/apps/shared.de.i18n @@ -89,3 +89,10 @@ 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 " diff --git a/apps/shared.en.i18n b/apps/shared.en.i18n index c18e948aa..2da4bfabc 100644 --- a/apps/shared.en.i18n +++ b/apps/shared.en.i18n @@ -89,3 +89,10 @@ 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 " diff --git a/apps/shared.es.i18n b/apps/shared.es.i18n index 800b30355..df5b55fdf 100644 --- a/apps/shared.es.i18n +++ b/apps/shared.es.i18n @@ -89,3 +89,10 @@ 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 " diff --git a/apps/shared.fr.i18n b/apps/shared.fr.i18n index 6bcacc18e..058514d0c 100644 --- a/apps/shared.fr.i18n +++ b/apps/shared.fr.i18n @@ -89,3 +89,10 @@ 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 " diff --git a/apps/shared.hu.i18n b/apps/shared.hu.i18n index b9be6807b..2a2dde2b6 100644 --- a/apps/shared.hu.i18n +++ b/apps/shared.hu.i18n @@ -89,3 +89,10 @@ 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 " diff --git a/apps/shared.it.i18n b/apps/shared.it.i18n index 4476ed58c..04472b553 100644 --- a/apps/shared.it.i18n +++ b/apps/shared.it.i18n @@ -89,3 +89,10 @@ 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 " diff --git a/apps/shared.nl.i18n b/apps/shared.nl.i18n index cd091b0dc..92bbbd66b 100644 --- a/apps/shared.nl.i18n +++ b/apps/shared.nl.i18n @@ -89,3 +89,10 @@ 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" diff --git a/apps/shared.pt.i18n b/apps/shared.pt.i18n index b68443df1..297cfeba7 100644 --- a/apps/shared.pt.i18n +++ b/apps/shared.pt.i18n @@ -89,3 +89,10 @@ 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 " diff --git a/apps/shared/Makefile b/apps/shared/Makefile index bd421f508..1d0530e73 100644 --- a/apps/shared/Makefile +++ b/apps/shared/Makefile @@ -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 \ diff --git a/apps/shared/color_cell.cpp b/apps/shared/color_cell.cpp new file mode 100644 index 000000000..a43e3f3ea --- /dev/null +++ b/apps/shared/color_cell.cpp @@ -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); +} + +} diff --git a/apps/shared/color_cell.h b/apps/shared/color_cell.h new file mode 100644 index 000000000..16967bdcb --- /dev/null +++ b/apps/shared/color_cell.h @@ -0,0 +1,42 @@ +#ifndef SHARED_COLOR_CELL_CONTROLLER_H +#define SHARED_COLOR_CELL_CONTROLLER_H + +#include +#include + +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 diff --git a/apps/shared/color_parameter_controller.cpp b/apps/shared/color_parameter_controller.cpp new file mode 100644 index 000000000..2b2e4ef8d --- /dev/null +++ b/apps/shared/color_parameter_controller.cpp @@ -0,0 +1,86 @@ +#include "color_parameter_controller.h" + +#include "function_app.h" +#include "../apps_container.h" +#include + +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 ColorParameterController::function() { + return functionStore()->modelForRecord(m_record); +} + +FunctionStore * ColorParameterController::functionStore() { + return FunctionApp::app()->functionStore(); +} + + +} diff --git a/apps/shared/color_parameter_controller.h b/apps/shared/color_parameter_controller.h new file mode 100644 index 000000000..416e94019 --- /dev/null +++ b/apps/shared/color_parameter_controller.h @@ -0,0 +1,44 @@ +#ifndef SHARED_COLOR_PARAM_CONTROLLER_H +#define SHARED_COLOR_PARAM_CONTROLLER_H + +#include +#include "function_store.h" +#include "color_cell.h" +#include + +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(); + SelectableTableView m_selectableTableView; + Ion::Storage::Record m_record; + I18n::Message m_title; + MessageTableCellWithColor m_cells[Palette::numberOfDataColors()]; +}; + +} + +#endif diff --git a/apps/shared/function.cpp b/apps/shared/function.cpp index 3f3150d6f..7248b6b6a 100644 --- a/apps/shared/function.cpp +++ b/apps/shared/function.cpp @@ -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(cursorY, buffer, bufferSize, precision); } diff --git a/apps/shared/function.h b/apps/shared/function.h index a5daa9c59..6fa039bac 100644 --- a/apps/shared/function.h +++ b/apps/shared/function.h @@ -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: diff --git a/apps/shared/list_parameter_controller.cpp b/apps/shared/list_parameter_controller.cpp index 27c11745f..e55e3bf2a 100644 --- a/apps/shared/list_parameter_controller.cpp +++ b/apps/shared/list_parameter_controller.cpp @@ -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); diff --git a/apps/shared/list_parameter_controller.h b/apps/shared/list_parameter_controller.h index 4ef2b616e..e7ffb0fc6 100644 --- a/apps/shared/list_parameter_controller.h +++ b/apps/shared/list_parameter_controller.h @@ -3,6 +3,7 @@ #include #include "function_store.h" +#include "color_parameter_controller.h" #include 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(); 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; }; }