M .gitmodules => .gitmodules +1 -0
@@ 59,6 59,7 @@
[submodule "module-bsp/board/rt1051/bsp/usb"]
path = module-bsp/board/rt1051/bsp/usb
url = ../usb_stack.git
+ branch = stable
[submodule "module-vfs/thirdparty/fatfs"]
path = module-vfs/thirdparty/fatfs
url = ../fatfs.git
M CMakeLists.txt => CMakeLists.txt +9 -5
@@ 281,7 281,7 @@ if (${PROJECT_TARGET} STREQUAL "TARGET_RT1051")
-w ${CMAKE_BINARY_DIR} ecoboot download
> ${ECOBOOT_DOWNLOAD_LOG}
COMMENT "Downloading ecoboot.bin"
- BYPRODUCTS ${ECOBOOT_FILE} ${ECOBOOT_DOWNLOAD_LOG}
+ BYPRODUCTS ${ECOBOOT_DOWNLOAD_LOG}
)
else()
message("ecoboot download with git")
@@ 290,11 290,13 @@ if (${PROJECT_TARGET} STREQUAL "TARGET_RT1051")
-w ${CMAKE_BINARY_DIR} ecoboot download
> ${ECOBOOT_DOWNLOAD_LOG}
COMMENT "Downloading ecoboot.bin"
- BYPRODUCTS ${ECOBOOT_FILE} ${ECOBOOT_DOWNLOAD_LOG}
+ BYPRODUCTS ${ECOBOOT_DOWNLOAD_LOG}
)
endif()
- add_custom_target(ecoboot.bin DEPENDS ${ECOBOOT_FILE})
+ if(NOT ${CMAKE_GENERATOR} STREQUAL "Ninja")
+ add_custom_target(ecoboot.bin DEPENDS ${ECOBOOT_FILE})
+ endif()
# generate version.json file (runs CMake script at build time)
set(VERSION_JSON ${CMAKE_BINARY_DIR}/version.json)
@@ 305,9 307,11 @@ if (${PROJECT_TARGET} STREQUAL "TARGET_RT1051")
-B ${CMAKE_BINARY_DIR}
-P ${CMAKE_SOURCE_DIR}/config/GenUpdateVersionJson.cmake
DEPENDS ecoboot.bin ${ECOBOOT_DOWNLOAD_LOG}
- BYPRODUCTS ${VERSION_JSON}
)
- add_custom_target(version.json DEPENDS ${VERSION_JSON})
+
+ if(NOT ${CMAKE_GENERATOR} STREQUAL "Ninja")
+ add_custom_target(version.json DEPENDS ${VERSION_JSON})
+ endif()
multicomp_install(PROGRAMS ${ECOBOOT_FILE} DESTINATION "./" COMPONENTS Standalone Update)
multicomp_install(FILES ${VERSION_JSON} DESTINATION "./" COMPONENTS Standalone Update)
M image/assets/lang/English.json => image/assets/lang/English.json +2 -0
@@ 158,6 158,8 @@
"app_notes_no_notes": "<text align='center' color='9'>No notes yet.<p>Press <b>left arrow</b> to add new.</p></text>",
"app_notes_search_no_results": "No notes found.",
+ "app_call_emergency_text": "Emergency call",
+
"app_calllog_title_main": "Calls",
"app_calllog_new_note": "New Note",
"app_calllog_save": "SAVE",
M module-apps/Application.cpp => module-apps/Application.cpp +3 -1
@@ 727,7 727,9 @@ namespace app
void Application::setLockScreenPasscodeOn(bool screenPasscodeOn) noexcept
{
lockScreenPasscodeIsOn = screenPasscodeOn;
- settings->setValue(settings::SystemProperties::lockScreenPasscodeIsOn, std::to_string(lockScreenPasscodeIsOn));
+ settings->setValue(settings::SystemProperties::lockScreenPasscodeIsOn,
+ std::to_string(lockScreenPasscodeIsOn),
+ settings::SettingsScope::Global);
}
bool Application::isLockScreenPasscodeOn() const noexcept
M module-apps/application-calendar/ApplicationCalendar.cpp => module-apps/application-calendar/ApplicationCalendar.cpp +1 -1
@@ 147,7 147,7 @@ namespace app
void ApplicationCalendar::destroyUserInterface()
{}
- void ApplicationCalendar::switchToNoEventsWindow(const std::string &title, const calendar::TimePoint &dateFilter)
+ void ApplicationCalendar::switchToNoEventsWindow(const std::string &title, const TimePoint &dateFilter)
{
if (equivalentWindow == EquivalentWindow::DayEventsWindow) {
popToWindow(gui::name::window::main_window);
M module-apps/application-calendar/ApplicationCalendar.hpp => module-apps/application-calendar/ApplicationCalendar.hpp +1 -2
@@ 55,8 55,7 @@ namespace app
}
void createUserInterface() override;
void destroyUserInterface() override;
- void switchToNoEventsWindow(const std::string &title = "",
- const calendar::TimePoint &dateFilter = calendar::TimePoint());
+ void switchToNoEventsWindow(const std::string &title = "", const TimePoint &dateFilter = TimePoint());
static const std::map<Reminder, const char *> reminderOptions;
static const std::map<Repeat, const char *> repeatOptions;
M module-apps/application-calendar/data/CalendarData.hpp => module-apps/application-calendar/data/CalendarData.hpp +3 -3
@@ 42,7 42,7 @@ class DayMonthData : public gui::SwitchData
{
protected:
std::string dayMonth;
- calendar::TimePoint dateFilter;
+ TimePoint dateFilter;
public:
DayMonthData() = default;
@@ 52,12 52,12 @@ class DayMonthData : public gui::SwitchData
return dayMonth;
};
- calendar::TimePoint getDateFilter()
+ TimePoint getDateFilter()
{
return dateFilter;
};
- virtual void setData(std::string dayMonthText, const calendar::TimePoint &dateNumb)
+ virtual void setData(std::string dayMonthText, const TimePoint &dateNumb)
{
dayMonth = dayMonthText;
dateFilter = dateNumb;
M module-apps/application-calendar/data/dateCommon.hpp => module-apps/application-calendar/data/dateCommon.hpp +27 -26
@@ 9,15 9,16 @@
#include <Utils.hpp>
#include <random>
+using Clock = std::chrono::system_clock;
+using TimePoint = std::chrono::time_point<Clock>;
+
namespace calendar
{
- using Clock = std::chrono::system_clock;
- using TimePoint = std::chrono::time_point<Clock>;
using YearMonthDay = date::year_month_day;
using YearMonthDayLast = date::year_month_day_last;
} // namespace calendar
-inline constexpr auto max_month_day = 48;
+inline constexpr auto max_month_day = 31;
enum class Reminder
{
@@ 43,7 44,7 @@ enum class Repeat
yearly
};
-inline constexpr calendar::TimePoint TIME_POINT_INVALID = date::sys_days{date::January / 1 / 1970};
+inline constexpr TimePoint TIME_POINT_INVALID = date::sys_days{date::January / 1 / 1970};
inline constexpr uint32_t yearDigitsNumb = 4, monthDigitsNumb = 2, dayDigitsNumb = 2, HourDigitsNumb = 2,
MinDigitsNumb = 2, SecDigitsNumb = 2;
@@ 88,34 89,34 @@ inline time_t GetAsUTCTime(int year, int month, int day, int hour = 0, int minut
return basetime + GetDiffLocalWithUTCTime();
}
-inline calendar::TimePoint TimePointFromTimeT(const time_t &time)
+inline TimePoint TimePointFromTimeT(const time_t &time)
{
return std::chrono::system_clock::from_time_t(time);
}
-inline time_t TimePointToTimeT(const calendar::TimePoint &tp)
+inline time_t TimePointToTimeT(const TimePoint &tp)
{
return std::chrono::system_clock::to_time_t(tp);
}
-inline calendar::TimePoint TimePointNow()
+inline TimePoint TimePointNow()
{
utils::time::Timestamp timestamp;
return TimePointFromTimeT(timestamp.getTime());
}
-inline std::string TimePointToString(const calendar::TimePoint &tp)
+inline std::string TimePointToString(const TimePoint &tp)
{
return date::format("%F %T", std::chrono::time_point_cast<std::chrono::seconds>(tp));
}
-inline auto TimePointToHourMinSec(const calendar::TimePoint &tp)
+inline auto TimePointToHourMinSec(const TimePoint &tp)
{
auto dp = date::floor<date::days>(tp);
return date::make_time(tp - dp);
}
-inline uint32_t TimePointToHour24H(const calendar::TimePoint &tp)
+inline uint32_t TimePointToHour24H(const TimePoint &tp)
{
auto time = TimePointToTimeT(tp);
utils::time::Timestamp timestamp(time);
@@ 123,7 124,7 @@ inline uint32_t TimePointToHour24H(const calendar::TimePoint &tp)
return hour;
}
-inline uint32_t TimePointToMinutes(const calendar::TimePoint &tp)
+inline uint32_t TimePointToMinutes(const TimePoint &tp)
{
auto time = TimePointToTimeT(tp);
utils::time::Timestamp timestamp(time);
@@ 131,7 132,7 @@ inline uint32_t TimePointToMinutes(const calendar::TimePoint &tp)
return minute;
}
-inline calendar::TimePoint getFirstWeekDay(const calendar::TimePoint &tp)
+inline TimePoint getFirstWeekDay(const TimePoint &tp)
{
auto time_of_day = TimePointToHourMinSec(tp);
auto yearMonthDay = date::year_month_day{date::floor<date::days>(tp)};
@@ 145,12 146,12 @@ inline calendar::TimePoint getFirstWeekDay(const calendar::TimePoint &tp)
return finalDateTime;
}
-inline std::string TimePointToString(const calendar::TimePoint &tp, date::months months)
+inline std::string TimePointToString(const TimePoint &tp, date::months months)
{
date::year_month_day yearMonthDay = date::year_month_day{date::floor<date::days>(tp)};
date::year_month_day yearMonthDayLast = yearMonthDay.year() / yearMonthDay.month() / date::last;
- calendar::TimePoint timePoint;
+ TimePoint timePoint;
if ((static_cast<unsigned>(yearMonthDay.month()) + months.count()) <= 12) {
if (yearMonthDayLast.day() == yearMonthDay.day()) {
@@ 194,38 195,38 @@ inline std::string TimePointToString(const calendar::TimePoint &tp, date::years
std::chrono::time_point_cast<std::chrono::seconds>(timePoint + time_of_day.hours() + time_of_day.minutes()));
}
-inline std::string TimePointToLocalizedDateString(const calendar::TimePoint &tp, const std::string format = "")
+inline std::string TimePointToLocalizedDateString(const TimePoint &tp, const std::string format = "")
{
auto time = TimePointToTimeT(tp);
utils::time::Date timestamp(time);
return timestamp.str(format);
}
-inline std::string TimePointToLocalizedTimeString(const calendar::TimePoint &tp, const std::string format = "")
+inline std::string TimePointToLocalizedTimeString(const TimePoint &tp, const std::string format = "")
{
auto time = TimePointToTimeT(tp);
utils::time::Time timestamp(time);
return timestamp.str(format);
}
-inline calendar::TimePoint TimePointFromString(const char *s1)
+inline TimePoint TimePointFromString(const char *s1)
{
- calendar::TimePoint tp;
+ TimePoint tp;
std::istringstream(s1) >> date::parse("%F %T", tp);
return tp;
}
-inline calendar::YearMonthDay TimePointToYearMonthDay(const calendar::TimePoint &tp)
+inline calendar::YearMonthDay TimePointToYearMonthDay(const TimePoint &tp)
{
return date::year_month_day{date::floor<date::days>(tp)};
}
-inline calendar::TimePoint TimePointFromYearMonthDay(const calendar::YearMonthDay &ymd)
+inline TimePoint TimePointFromYearMonthDay(const calendar::YearMonthDay &ymd)
{
return date::sys_days{ymd.year() / ymd.month() / ymd.day()};
}
-inline time_t TimePointToMin(const calendar::TimePoint &tp)
+inline time_t TimePointToMin(const TimePoint &tp)
{
auto time = TimePointToTimeT(tp);
auto duration = new utils::time::Duration(time);
@@ 233,7 234,7 @@ inline time_t TimePointToMin(const calendar::TimePoint &tp)
return minutes;
}
-inline uint32_t TimePointToHour12H(const calendar::TimePoint &tp)
+inline uint32_t TimePointToHour12H(const TimePoint &tp)
{
auto time = TimePointToTimeT(tp);
utils::time::Timestamp timestamp(time);
@@ 244,7 245,7 @@ inline uint32_t TimePointToHour12H(const calendar::TimePoint &tp)
return hour;
}
-inline std::string TimePointToHourString12H(const calendar::TimePoint &tp)
+inline std::string TimePointToHourString12H(const TimePoint &tp)
{
auto hour =
utils::time::Timestamp(TimePointToTimeT(tp)).get_UTC_date_time_sub_value(utils::time::GetParameters::Hour);
@@ 252,14 253,14 @@ inline std::string TimePointToHourString12H(const calendar::TimePoint &tp)
return utils::to_string(hour12h);
}
-inline std::string TimePointToHourString24H(const calendar::TimePoint &tp)
+inline std::string TimePointToHourString24H(const TimePoint &tp)
{
auto hour =
utils::time::Timestamp(TimePointToTimeT(tp)).get_UTC_date_time_sub_value(utils::time::GetParameters::Hour);
return utils::to_string(hour);
}
-inline std::string TimePointToMinutesString(const calendar::TimePoint &tp)
+inline std::string TimePointToMinutesString(const TimePoint &tp)
{
auto minute = TimePointToMinutes(tp);
auto minuteString = std::to_string(minute);
@@ 270,7 271,7 @@ inline std::string TimePointToMinutesString(const calendar::TimePoint &tp)
}
// 0: Monday, 1: Tuesday ... 6: Sunday
-inline unsigned int WeekdayIndexFromTimePoint(const calendar::TimePoint &tp)
+inline unsigned int WeekdayIndexFromTimePoint(const TimePoint &tp)
{
auto ymw = date::year_month_weekday{std::chrono::floor<date::days>(tp)};
return ymw.weekday().iso_encoding() - 1;
M module-apps/application-calendar/models/DayEventsModel.cpp => module-apps/application-calendar/models/DayEventsModel.cpp +5 -4
@@ 6,7 6,7 @@
#include "application-calendar/data/CalendarData.hpp"
#include "application-calendar/ApplicationCalendar.hpp"
#include <ListView.hpp>
-#include <queries/calendar/QueryEventsGetFiltered.hpp>
+#include <queries/calendar/QueryEventsGetFilteredByDay.hpp>
#include <service-db/DBServiceAPI.hpp>
#include <service-db/QueryMessage.hpp>
#include <module-db/queries/RecordQuery.hpp>
@@ 27,7 27,7 @@ unsigned int DayEventsModel::getMinimalItemHeight() const
void DayEventsModel::requestRecords(const uint32_t offset, const uint32_t limit)
{
- auto query = std::make_unique<db::query::events::GetFiltered>(filterFrom, filterTill, offset, limit);
+ auto query = std::make_unique<db::query::events::GetFilteredByDay>(filterFrom, offset, limit);
auto task = app::AsyncQuery::createFromQuery(std::move(query), db::Interface::Name::Events);
task->setCallback([this](auto response) { return handleQueryResponse(response); });
task->execute(application, this);
@@ 63,7 63,7 @@ bool DayEventsModel::updateRecords(std::vector<EventsRecord> records)
auto DayEventsModel::handleQueryResponse(db::QueryResult *queryResult) -> bool
{
- if (auto response = dynamic_cast<db::query::events::GetFilteredResult *>(queryResult); response != nullptr) {
+ if (auto response = dynamic_cast<db::query::events::GetFilteredByDayResult *>(queryResult); response != nullptr) {
if (recordsCount != (response->getCountResult())) {
recordsCount = response->getCountResult();
list->rebuildList(style::listview::RebuildType::Full, 0, true);
@@ 95,8 95,9 @@ auto DayEventsModel::handleQueryResponse(db::QueryResult *queryResult) -> bool
return false;
}
-void DayEventsModel::setFilters(calendar::TimePoint from, calendar::TimePoint till, const std::string &dayMonth)
+void DayEventsModel::setFilters(TimePoint from, TimePoint till, const std::string &dayMonth)
{
+ /// TODO: change to one filter
this->filterFrom = from;
this->filterTill = till;
this->dayMonthTitle = dayMonth;
M module-apps/application-calendar/models/DayEventsModel.hpp => module-apps/application-calendar/models/DayEventsModel.hpp +3 -3
@@ 15,13 15,13 @@ class DayEventsModel : public app::DatabaseModel<EventsRecord>,
{
app::Application *application = nullptr;
std::string dayMonthTitle;
- calendar::TimePoint filterFrom = TIME_POINT_INVALID;
- calendar::TimePoint filterTill = TIME_POINT_INVALID;
+ TimePoint filterFrom = TIME_POINT_INVALID;
+ TimePoint filterTill = TIME_POINT_INVALID;
public:
DayEventsModel(app::Application *app);
- void setFilters(calendar::TimePoint from, calendar::TimePoint till, const std::string &dayMonth);
+ void setFilters(TimePoint from, TimePoint till, const std::string &dayMonth);
bool updateRecords(std::vector<EventsRecord> records) override;
auto handleQueryResponse(db::QueryResult *) -> bool;
M module-apps/application-calendar/models/MonthModel.cpp => module-apps/application-calendar/models/MonthModel.cpp +60 -7
@@ 3,9 3,34 @@
#include "MonthModel.hpp"
#include <time/time_locale.hpp>
+#include <time/time_conversion.hpp>
+
+date::year_month_day MonthModel::getYearMonthDayFromTimePoint(TimePoint timePoint) const
+{
+ return date::year_month_day{date::floor<date::days>(timePoint)};
+}
+
+uint32_t MonthModel::getEventDurationInDays(const EventsRecord &record) const
+{
+ auto eventStartDuration = utils::time::Duration(TimePointToTimeT(record.date_from));
+ auto eventEndDuration = utils::time::Duration(TimePointToTimeT(record.date_till));
+ auto startEventDurationSinceEpochInDaysRoundedDown =
+ (eventStartDuration.getHours() - eventStartDuration.getHours() % utils::time::hoursInday) /
+ utils::time::hoursInday;
+ auto endEventDurationSinceEpochInDaysRoundedDown =
+ (eventEndDuration.getHours() - eventEndDuration.getHours() % utils::time::hoursInday) / utils::time::hoursInday;
+ return endEventDurationSinceEpochInDaysRoundedDown - startEventDurationSinceEpochInDaysRoundedDown;
+}
+
+uint32_t MonthModel::getDayIndex(TimePoint date) const
+{
+ date::year_month_day recordDate = TimePointToYearMonthDay(date);
+ return (static_cast<unsigned>(recordDate.day()) - 1);
+}
MonthModel::MonthModel(date::year_month_day yearMonthDay)
{
+ this->yearMonth = YearMonth(yearMonthDay);
this->month = yearMonthDay.month();
this->year = yearMonthDay.year();
date::year_month_day_last yearMonthDayLast = this->year / this->month / date::last;
@@ 14,6 39,35 @@ MonthModel::MonthModel(date::year_month_day yearMonthDay)
this->firstWeekDayNumb = date::weekday{yearMonthDayFirst}.c_encoding();
}
+void MonthModel::markEventsInDays(const std::vector<EventsRecord> &records, std::array<bool, 31> &isDayEmpty)
+{
+ for (auto &rec : records) {
+ auto eventYearMonthFrom = YearMonth(getYearMonthDayFromTimePoint(rec.date_from));
+ auto eventYearMonthTill = YearMonth(getYearMonthDayFromTimePoint(rec.date_till));
+
+ if (eventYearMonthFrom < this->yearMonth && this->yearMonth < eventYearMonthTill) {
+ for (uint32_t i = 0; i < max_month_day; i++) {
+ isDayEmpty[i] = false;
+ }
+ return;
+ }
+
+ int durationInDays = getEventDurationInDays(rec);
+
+ if (this->yearMonth == eventYearMonthFrom) {
+ for (int i = getDayIndex(rec.date_from); i < max_month_day && durationInDays >= 0; i++, durationInDays--) {
+ isDayEmpty[i] = false;
+ }
+ }
+
+ if (this->yearMonth == eventYearMonthTill) {
+ for (int i = getDayIndex(rec.date_till); i >= 0 && durationInDays >= 0; i--, durationInDays--) {
+ isDayEmpty[i] = false;
+ }
+ }
+ }
+}
+
date::year MonthModel::getYear()
{
return year;
@@ 52,18 106,17 @@ std::vector<std::string> MonthModel::split(const std::string &s, char delim)
std::string MonthModel::getMonthText()
{
- unsigned int monthUInt = static_cast<unsigned>(month);
- std::string monthStr = utils::time::Locale::get_month(utils::time::Locale::Month(monthUInt - 1));
+ auto monthUInt = static_cast<unsigned>(month);
+ std::string monthStr = utils::time::Locale::get_month(utils::time::Locale::Month(monthUInt - 1));
return monthStr;
}
std::string MonthModel::getMonthYearText()
{
- int yearUInt = static_cast<decltype(yearUInt)>(year);
- std::string yearStr = std::to_string(yearUInt);
- std::string monthStr;
- unsigned int monthUInt = static_cast<unsigned>(month);
- monthStr = utils::time::Locale::get_month(utils::time::Locale::Month(monthUInt - 1));
+ auto yearInt = static_cast<int>(year);
+ std::string yearStr = std::to_string(yearInt);
+ auto monthUInt = static_cast<unsigned>(month);
+ std::string monthStr = utils::time::Locale::get_month(utils::time::Locale::Month(monthUInt - 1));
return monthStr + " " + yearStr;
}
M module-apps/application-calendar/models/MonthModel.hpp => module-apps/application-calendar/models/MonthModel.hpp +51 -7
@@ 13,21 13,59 @@
#include <string>
#include <vector>
#include <module-apps/application-calendar/data/dateCommon.hpp>
+#include <module-db/Interface/EventsRecord.hpp>
-class MonthModel
+class YearMonth
{
- public:
- date::month month;
- unsigned int lastDay;
- // first week offset
- uint32_t firstWeekDayNumb;
date::year year;
+ date::month month;
public:
- MonthModel(date::year_month_day ymd);
+ YearMonth() = default;
+ explicit YearMonth(date::year_month_day ymd) : year{ymd.year()}, month{ymd.month()} {};
+
+ bool operator>(const YearMonth &other) const noexcept
+ {
+ if (this->year != other.year) {
+ return this->year > other.year;
+ }
+ else {
+ return this->month > other.month;
+ }
+ };
+
+ bool operator==(const YearMonth &other) const noexcept
+ {
+ return this->month == other.month && this->year == other.year;
+ };
+
+ bool operator!=(const YearMonth &other)
+ {
+ return !(*this == other);
+ };
+
+ bool operator<(const YearMonth &other)
+ {
+ return !(*this > other) && (*this != other);
+ };
+};
+
+class MonthModel
+{
+ private:
+ YearMonth yearMonth;
+
+ [[nodiscard]] date::year_month_day getYearMonthDayFromTimePoint(TimePoint timePoint) const;
+ [[nodiscard]] uint32_t getEventDurationInDays(const EventsRecord &records) const;
+ [[nodiscard]] uint32_t getDayIndex(TimePoint date) const;
+
+ public:
+ explicit MonthModel(date::year_month_day yearMonthDay);
MonthModel() = default;
virtual ~MonthModel() = default;
+ void markEventsInDays(const std::vector<EventsRecord> &records, std::array<bool, 31> &isDayEmpty);
+
date::year getYear();
date::month getMonth();
uint32_t getLastDay();
@@ 35,4 73,10 @@ class MonthModel
std::string getMonthYearText();
std::string getMonthText();
std::vector<std::string> split(const std::string &s, char delim);
+
+ date::month month;
+ uint32_t lastDay;
+ // first week offset
+ uint32_t firstWeekDayNumb;
+ date::year year;
};
M module-apps/application-calendar/widgets/EventTimeItem.cpp => module-apps/application-calendar/widgets/EventTimeItem.cpp +3 -3
@@ 433,9 433,9 @@ namespace gui
}
}
- calendar::TimePoint EventTimeItem::calculateEventTime(calendar::YearMonthDay date,
- std::chrono::hours hours,
- std::chrono::minutes minutes)
+ TimePoint EventTimeItem::calculateEventTime(calendar::YearMonthDay date,
+ std::chrono::hours hours,
+ std::chrono::minutes minutes)
{
return TimePointFromYearMonthDay(date) + hours + minutes;
}
M module-apps/application-calendar/widgets/EventTimeItem.hpp => module-apps/application-calendar/widgets/EventTimeItem.hpp +3 -3
@@ 43,9 43,9 @@ namespace gui
std::chrono::minutes end_hour,
uint32_t start_minutes,
uint32_t end_minutes);
- calendar::TimePoint calculateEventTime(calendar::YearMonthDay date,
- std::chrono::hours hours,
- std::chrono::minutes minutes);
+ TimePoint calculateEventTime(calendar::YearMonthDay date,
+ std::chrono::hours hours,
+ std::chrono::minutes minutes);
public:
EventTimeItem(const std::string &description,
M module-apps/application-calendar/widgets/MonthBox.cpp => module-apps/application-calendar/widgets/MonthBox.cpp +1 -1
@@ 16,7 16,7 @@ namespace gui
const uint32_t &dayWidth,
const uint32_t &dayHeight,
const std::unique_ptr<MonthModel> &model,
- bool *isDayEmpty)
+ std::array<bool, 31> &isDayEmpty)
: GridLayout(parent, style::window::default_left_margin, offsetTop, width, height, {dayWidth, dayHeight})
{
LOG_DEBUG("Call MonthBox constructor");
M module-apps/application-calendar/widgets/MonthBox.hpp => module-apps/application-calendar/widgets/MonthBox.hpp +1 -1
@@ 19,7 19,7 @@ namespace gui
const uint32_t &dayWidth,
const uint32_t &dayHeight,
const std::unique_ptr<MonthModel> &model,
- bool *isDayEmpty);
+ std::array<bool, 31> &isDayEmpty);
~MonthBox() override = default;
std::string month;
M module-apps/application-calendar/windows/AllEventsWindow.hpp => module-apps/application-calendar/windows/AllEventsWindow.hpp +1 -1
@@ 16,7 16,7 @@ namespace gui
gui::Image *leftArrowImage = nullptr;
gui::Image *newDayEventImage = nullptr;
- calendar::TimePoint dateFilter = TimePointNow();
+ TimePoint dateFilter = TimePointNow();
gui::ListView *allEventsList = nullptr;
std::shared_ptr<AllEventsModel> allEventsModel = nullptr;
M module-apps/application-calendar/windows/CalendarMainWindow.cpp => module-apps/application-calendar/windows/CalendarMainWindow.cpp +3 -8
@@ 29,12 29,12 @@ namespace gui
buildInterface();
}
- void CalendarMainWindow::refresh()
+ void CalendarMainWindow::refresh(const std::vector<EventsRecord> &records)
{
erase(dateLabel);
monthBox->erase();
-
monthModel = std::make_unique<MonthModel>(actualDate);
+ monthModel->markEventsInDays(records, isDayEmpty);
std::string dateText = monthModel->getMonthYearText();
this->buildMonth(monthModel);
this->buildDateLabel(dateText);
@@ 213,12 213,7 @@ namespace gui
std::fill(std::begin(isDayEmpty), std::end(isDayEmpty), true);
if (auto response = dynamic_cast<db::query::events::GetFilteredResult *>(queryResult)) {
const auto records = response->getResult();
- for (auto &rec : records) {
- date::year_month_day recordDate = TimePointToYearMonthDay(rec.date_from);
- uint32_t dayNumb = static_cast<unsigned>(recordDate.day());
- isDayEmpty[dayNumb - 1] = false;
- }
- refresh();
+ refresh(records);
return true;
}
if (auto response = dynamic_cast<db::query::events::GetAllResult *>(queryResult)) {
M module-apps/application-calendar/windows/CalendarMainWindow.hpp => module-apps/application-calendar/windows/CalendarMainWindow.hpp +2 -2
@@ 24,7 24,7 @@ namespace gui
class CalendarMainWindow : public gui::AppWindow, public app::AsyncCallbackReceiver
{
- bool isDayEmpty[31];
+ std::array<bool, 31> isDayEmpty;
uint32_t offsetFromTop = 0;
uint32_t monthWidth = 0;
uint32_t monthHeight = 0;
@@ 41,7 41,7 @@ namespace gui
CalendarMainWindow(app::Application *app, const std::string &name);
void rebuild() override;
- void refresh();
+ void refresh(const std::vector<EventsRecord> &records);
void filterRequest();
void buildMonth(std::unique_ptr<MonthModel> &model);
void buildDateLabel(std::string actualDateTime);
M module-apps/application-calendar/windows/DayEventsWindow.hpp => module-apps/application-calendar/windows/DayEventsWindow.hpp +1 -1
@@ 19,7 19,7 @@ namespace gui
class DayEventsWindow : public gui::AppWindow
{
std::string dayMonthTitle;
- calendar::TimePoint filterFrom;
+ TimePoint filterFrom;
gui::Image *leftArrowImage = nullptr;
gui::Image *newDayEventImage = nullptr;
gui::ListView *dayEventsList = nullptr;
M module-apps/application-call/ApplicationCall.cpp => module-apps/application-call/ApplicationCall.cpp +16 -19
@@ 47,6 47,10 @@ namespace app
switchWindow(window::name_enterNumber, std::forward<decltype(data)>(data));
return msgHandled();
});
+ addActionReceiver(manager::actions::EmergencyDial, [this](auto &&data) {
+ switchWindow(app::window::name_emergencyCall, std::forward<decltype(data)>(data));
+ return msgHandled();
+ });
}
// number of seconds after end call to switch back to previous application
@@ 211,30 215,23 @@ namespace app
{
LOG_INFO("add contact information: %s", number.c_str());
- auto searchResults = DBServiceAPI::ContactSearch(this, UTF8{}, UTF8{}, number);
- if (const auto resultsSize = searchResults->size(); resultsSize > 1) {
- LOG_FATAL("Found more than one contact for number %s", number.c_str());
- for (auto i : *searchResults) {
- LOG_FATAL("ContactID = %" PRIu32, i.ID);
- }
- }
- else if (resultsSize == 1) {
- const auto &contactRecord = searchResults->front();
+ auto numberView = utils::PhoneNumber(number).getView();
+ auto searchResults = DBServiceAPI::MatchContactByPhoneNumber(this, numberView);
+ if (searchResults != nullptr) {
LOG_INFO("Found contact matching search num %s : contact ID %" PRIu32 " - %s %s",
number.c_str(),
- contactRecord.ID,
- contactRecord.primaryName.c_str(),
- contactRecord.alternativeName.c_str());
- app::manager::Controller::sendAction(
- this,
- app::manager::actions::AddContact,
- std::make_unique<PhonebookItemData>(std::make_shared<ContactRecord>(contactRecord)));
+ searchResults->ID,
+ searchResults->primaryName.c_str(),
+ searchResults->alternativeName.c_str());
+ app::manager::Controller::sendAction(this,
+ app::manager::actions::EditContact,
+ std::make_unique<PhonebookItemData>(std::move(searchResults)));
}
else {
- ContactRecord contactRecord;
- contactRecord.numbers.emplace_back(ContactRecord::Number(utils::PhoneNumber(number).getView()));
+ auto contactRecord = std::make_shared<ContactRecord>();
+ contactRecord->numbers.emplace_back(std::move(numberView));
- auto data = std::make_unique<PhonebookItemData>(std::make_shared<ContactRecord>(contactRecord));
+ auto data = std::make_unique<PhonebookItemData>(std::move(contactRecord));
data->ignoreCurrentWindowOnStack = true;
app::manager::Controller::sendAction(
this, manager::actions::AddContact, std::move(data), manager::OnSwitchBehaviour::RunInBackground);
M module-apps/application-call/ApplicationCall.hpp => module-apps/application-call/ApplicationCall.hpp +5 -1
@@ 24,6 24,7 @@ namespace app
inline constexpr auto name_emergencyCall = "EmergencyCallWindow";
inline constexpr auto name_duplicatedContact = "DuplicatedContactWindow";
inline constexpr auto name_dialogConfirm = "DialogConfirm";
+ inline constexpr auto name_number = "NumberWindow";
} // namespace window
inline constexpr auto ringtone_path = "assets/audio/Ringtone-drum2.mp3"; // Should bo moved to database
@@ 100,7 101,10 @@ namespace app
{
static auto GetManifest() -> manager::ApplicationManifest
{
- return {{manager::actions::Launch, manager::actions::Call, manager::actions::Dial}};
+ return {{manager::actions::Launch,
+ manager::actions::Call,
+ manager::actions::Dial,
+ manager::actions::EmergencyDial}};
}
};
} /* namespace app */
M module-apps/application-call/CMakeLists.txt => module-apps/application-call/CMakeLists.txt +4 -2
@@ 22,13 22,15 @@ target_sources( ${PROJECT_NAME}
"${CMAKE_CURRENT_LIST_DIR}/windows/EmergencyCallWindow.cpp"
"${CMAKE_CURRENT_LIST_DIR}/windows/CallWindow.cpp"
"${CMAKE_CURRENT_LIST_DIR}/widgets/StateIcons.cpp"
- PUBLIC
+ "${CMAKE_CURRENT_LIST_DIR}/windows/NumberWindow.cpp"
+ PUBLIC
"${CMAKE_CURRENT_LIST_DIR}/ApplicationCall.hpp"
"${CMAKE_CURRENT_LIST_DIR}/windows/EnterNumberWindow.hpp"
"${CMAKE_CURRENT_LIST_DIR}/windows/EmergencyCallWindow.hpp"
"${CMAKE_CURRENT_LIST_DIR}/windows/CallWindow.hpp"
"${CMAKE_CURRENT_LIST_DIR}/data/CallSwitchData.hpp"
-)
+ "${CMAKE_CURRENT_LIST_DIR}/windows/NumberWindow.hpp"
+ )
target_link_libraries(${PROJECT_NAME}
PRIVATE
M module-apps/application-call/data/CallAppStyle.hpp => module-apps/application-call/data/CallAppStyle.hpp +9 -1
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 36,6 36,14 @@ namespace callAppStyle
inline constexpr auto borderW = 1U;
} // namespace numberLabel
+ namespace numberDescriptionLabel
+ {
+ inline constexpr auto x = 60U;
+ inline constexpr auto y = 254U;
+ inline constexpr auto w = style::window_width - 2 * x;
+ inline constexpr auto h = 20U;
+ } // namespace numberDescriptionLabel
+
namespace icon
{
inline constexpr auto x_margin = 20U;
M module-apps/application-call/windows/EmergencyCallWindow.cpp => module-apps/application-call/windows/EmergencyCallWindow.cpp +17 -29
@@ 1,52 1,40 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
-#include "../data/CallSwitchData.hpp"
-#include "../ApplicationCall.hpp"
-#include <service-appmgr/model/ApplicationManager.hpp>
-
-#include <i18n/i18n.hpp>
#include "EmergencyCallWindow.hpp"
-#include <cassert>
+#include "application-call/data/CallAppStyle.hpp"
+
+#include <service-appmgr/Controller.hpp>
namespace gui
{
EmergencyCallWindow::EmergencyCallWindow(app::Application *app, app::EnterNumberWindowInterface *interface)
- : EnterNumberWindow(app, interface, app::window::name_emergencyCall)
+ : NumberWindow(app, interface, app::window::name_emergencyCall)
{
- assert(app != nullptr);
- assert(interface != nullptr);
- numberLabel->setText(utils::localize.get("app_call_emergency"));
+ buildInterface();
}
- void EmergencyCallWindow::rebuild()
- {}
void EmergencyCallWindow::buildInterface()
{
- AppWindow::buildInterface();
- }
- void EmergencyCallWindow::destroyInterface()
- {
- AppWindow::destroyInterface();
- }
-
- bool EmergencyCallWindow::onInput(const InputEvent &inputEvent)
- {
- bool ret = EnterNumberWindow::onInput(inputEvent);
+ using namespace callAppStyle;
+ NumberWindow::buildInterface();
- // if( number.empty() ) {
- // numberLabel->setText( utils::localize.get("app_call_emergency") );
- // }
+ bottomBar->setText(BottomBar::Side::CENTER, utils::localize.get("app_phonebook_ice_contacts_title"));
+ bottomBar->setText(BottomBar::Side::RIGHT, utils::localize.get(style::strings::common::back));
- return ret;
+ numberDescriptionLabel->setText(utils::localize.get("app_call_emergency_text"));
}
- bool EmergencyCallWindow::handleSwitchData(SwitchData *data)
+
+ bool EmergencyCallWindow::onInput(const InputEvent &inputEvent)
{
- bool ret = EnterNumberWindow::handleSwitchData(data);
+ if (inputEvent.is(gui::KeyCode::KEY_ENTER)) {
+ app::manager::Controller::sendAction(application, app::manager::actions::ShowEmergencyContacts);
+ return true;
+ }
- return ret;
+ return NumberWindow::onInput(inputEvent);
}
} /* namespace gui */
M module-apps/application-call/windows/EmergencyCallWindow.hpp => module-apps/application-call/windows/EmergencyCallWindow.hpp +3 -5
@@ 3,22 3,20 @@
#pragma once
-#include "EnterNumberWindow.hpp"
+#include "NumberWindow.hpp"
namespace gui
{
- class EmergencyCallWindow : public EnterNumberWindow
+ class EmergencyCallWindow : public NumberWindow
{
public:
EmergencyCallWindow(app::Application *app, app::EnterNumberWindowInterface *interface);
+ ~EmergencyCallWindow() override = default;
bool onInput(const InputEvent &inputEvent) override;
- bool handleSwitchData(SwitchData *data) override;
- void rebuild() override;
void buildInterface() override;
- void destroyInterface() override;
};
} /* namespace gui */
M module-apps/application-call/windows/EnterNumberWindow.cpp => module-apps/application-call/windows/EnterNumberWindow.cpp +6 -135
@@ 3,9 3,8 @@
#include "EnterNumberWindow.hpp"
-#include "../ApplicationCall.hpp"
-#include "../data/CallAppStyle.hpp"
-#include "../data/CallSwitchData.hpp"
+#include "application-call/data/CallAppStyle.hpp"
+#include "application-call/data/CallSwitchData.hpp"
#include <ContactRecord.hpp>
#include <country.hpp>
@@ 19,52 18,25 @@
#include <cassert>
-using namespace utils;
-
namespace gui
{
- using namespace callAppStyle;
- using namespace callAppStyle::enterNumberWindow;
-
EnterNumberWindow::EnterNumberWindow(app::Application *app,
app::EnterNumberWindowInterface *interface,
std::string windowName)
- : AppWindow(app, windowName), interface(interface), currentCountry(defaultCountry),
- numberUtil(*PhoneNumberUtil::GetInstance())
+ : NumberWindow(app, interface, std::move(windowName))
{
- assert(interface != nullptr);
- assert(app != nullptr);
- switchFormatter(country::getAlpha2Code(currentCountry));
buildInterface();
}
- void EnterNumberWindow::setNumberLabel(const std::string num)
- {
- numberLabel->setText(num);
-
- if (numberLabel->getText().length() == 0) {
- bottomBar->setText(BottomBar::Side::RIGHT, utils::localize.get(style::strings::common::back));
- return;
- }
- bottomBar->setText(BottomBar::Side::RIGHT, utils::localize.get("app_call_clear"));
- }
-
void EnterNumberWindow::buildInterface()
{
+ using namespace callAppStyle;
+ using namespace callAppStyle::enterNumberWindow;
+ NumberWindow::buildInterface();
- AppWindow::buildInterface();
-
- bottomBar->setText(BottomBar::Side::LEFT, utils::localize.get("app_call_call"));
bottomBar->setText(BottomBar::Side::CENTER, utils::localize.get("common_add"));
bottomBar->setText(BottomBar::Side::RIGHT, utils::localize.get("app_call_clear"));
- numberLabel = new gui::Label(this, numberLabel::x, numberLabel::y, numberLabel::w, numberLabel::h);
- numberLabel->setPenWidth(numberLabel::borderW);
- numberLabel->setFont(style::window::font::largelight);
- numberLabel->setEdges(RectangleEdge::Bottom);
- numberLabel->setAlignment(gui::Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Top));
- numberLabel->setEllipsis(Ellipsis::Left);
-
newContactIcon = new gui::AddContactIcon(this, newContactIcon::x, newContactIcon::y);
newContactIcon->activatedCallback = [=](gui::Item &item) { return addNewContact(); };
setFocusItem(newContactIcon);
@@ 76,69 48,6 @@ namespace gui
return true;
}
- void EnterNumberWindow::destroyInterface()
- {
- erase();
- }
-
- bool EnterNumberWindow::onInput(const InputEvent &inputEvent)
- {
- auto code = translator.handle(inputEvent.key, InputMode({InputMode::phone}).get());
- if (inputEvent.state == InputEvent::State::keyReleasedShort) {
- // Call function
- if (inputEvent.keyCode == KeyCode::KEY_LF) {
- interface->handleCallEvent(enteredNumber);
- return true;
- }
- // Clear/back function
- else if (inputEvent.keyCode == KeyCode::KEY_RF) {
- // if there isn't any char in phone number field return to previous application
- if (enteredNumber.empty()) {
- formatter->Clear();
- app::manager::Controller::switchBack(application);
- }
- // if there is the last char just clear input
- else if (enteredNumber.size() == 1) {
- clearInput();
- }
- else {
- // remove last digit and reformat entered number otherwise
- enteredNumber = enteredNumber.substr(0, enteredNumber.size() - 1);
- initFormatterInput(enteredNumber);
- setNumberLabel(formattedNumber);
-
- application->refreshWindow(RefreshModes::GUI_REFRESH_FAST);
- }
- return true;
- }
- else if (code != 0) {
- addDigit(code);
- return true;
- }
- }
- else if (inputEvent.state == InputEvent::State::keyReleasedLong) {
- // erase all characters from phone number
- if (inputEvent.keyCode == KeyCode::KEY_RF) {
- // if there isn't any char in phone number field return to previous application
- if (enteredNumber.empty()) {
- app::manager::Controller::switchBack(application);
- return true;
- }
- clearInput();
-
- return true;
- }
- // long press of '0' key is translated to '+'
- else if (inputEvent.keyCode == KeyCode::KEY_0) {
- addDigit('+');
- return true;
- }
- }
-
- // check if any of the lower inheritance onInput methods catch the event
- return AppWindow::onInput(inputEvent);
- }
-
bool EnterNumberWindow::handleSwitchData(SwitchData *data)
{
if (data == nullptr) {
@@ 175,42 84,4 @@ namespace gui
return true;
}
-
- void EnterNumberWindow::switchFormatter(const std::string ®ionCode)
- {
- auto newFormatter = std::unique_ptr<Formatter>(numberUtil.GetAsYouTypeFormatter(regionCode));
- formatter.swap(newFormatter);
- LOG_INFO("Switched formatter to region: %s", regionCode.c_str());
- }
-
- void EnterNumberWindow::initFormatterInput(const std::string &number)
- {
- enteredNumber = number;
- formatter->Clear();
- for (auto c : number) {
- formatter->InputDigit(c, &formattedNumber);
- }
- }
-
- void EnterNumberWindow::addDigit(const std::string::value_type &digit)
- {
- enteredNumber += digit;
- formatter->InputDigit(digit, &formattedNumber);
- setNumberLabel(formattedNumber);
- application->refreshWindow(RefreshModes::GUI_REFRESH_FAST);
- }
-
- const std::string &EnterNumberWindow::getEnteredNumber() const noexcept
- {
- return enteredNumber;
- }
-
- void EnterNumberWindow::clearInput()
- {
- enteredNumber.clear();
- formattedNumber.clear();
- formatter->Clear();
- setNumberLabel("");
- application->refreshWindow(RefreshModes::GUI_REFRESH_FAST);
- }
} /* namespace gui */
M module-apps/application-call/windows/EnterNumberWindow.hpp => module-apps/application-call/windows/EnterNumberWindow.hpp +3 -48
@@ 3,43 3,14 @@
#pragma once
-#include "application-call/ApplicationCall.hpp"
-#include "application-call/widgets/StateIcons.hpp"
-
-#include <Application.hpp>
-#include <AppWindow.hpp>
-#include <ContactRecord.hpp>
-#include <country.hpp>
-#include <gui/input/Translator.hpp>
-#include <gui/widgets/BottomBar.hpp>
-#include <gui/widgets/Image.hpp>
-#include <gui/widgets/Label.hpp>
-#include <gui/widgets/TopBar.hpp>
-#include <gui/widgets/Window.hpp>
-
-#include <phonenumbers/phonenumberutil.h>
-#include <phonenumbers/asyoutypeformatter.h>
-
-#include <memory>
-#include <string>
+#include "NumberWindow.hpp"
namespace gui
{
- class EnterNumberWindow : public AppWindow
+ class EnterNumberWindow : public NumberWindow
{
- public:
- using CountryCode = utils::country::Id;
-
private:
- using PhoneNumberUtil = i18n::phonenumbers::PhoneNumberUtil;
- using Formatter = i18n::phonenumbers::AsYouTypeFormatter;
-
- protected:
- app::EnterNumberWindowInterface *interface = nullptr;
- gui::Label *numberLabel = nullptr;
- gui::AddContactIcon *newContactIcon = nullptr;
-
- void setNumberLabel(const std::string num);
+ gui::AddContactIcon *newContactIcon = nullptr;
public:
EnterNumberWindow(app::Application *app,
@@ 47,27 18,11 @@ namespace gui
std::string windowName = app::window::name_enterNumber);
~EnterNumberWindow() override = default;
- auto onInput(const InputEvent &inputEvent) -> bool override;
auto handleSwitchData(SwitchData *data) -> bool override;
- [[nodiscard]] auto getEnteredNumber() const noexcept -> const std::string &;
void buildInterface() override;
- void destroyInterface() override;
-
- private:
- CountryCode defaultCountry = utils::country::defaultCountry;
- CountryCode currentCountry;
- gui::KeyInputMappedTranslation translator;
- PhoneNumberUtil &numberUtil;
- std::unique_ptr<Formatter> formatter;
- std::string formattedNumber;
- std::string enteredNumber;
auto addNewContact() -> bool;
- void switchFormatter(const std::string &countryCode);
- void initFormatterInput(const std::string &number);
- void addDigit(const std::string::value_type &digit);
- void clearInput();
};
} /* namespace gui */
A module-apps/application-call/windows/NumberWindow.cpp => module-apps/application-call/windows/NumberWindow.cpp +177 -0
@@ 0,0 1,177 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "NumberWindow.hpp"
+
+#include "application-call/ApplicationCall.hpp"
+#include "application-call/data/CallAppStyle.hpp"
+#include "application-call/data/CallSwitchData.hpp"
+
+#include <ContactRecord.hpp>
+#include <gui/widgets/BottomBar.hpp>
+#include <gui/widgets/Image.hpp>
+#include <gui/widgets/Label.hpp>
+#include <gui/widgets/TopBar.hpp>
+#include <gui/widgets/Window.hpp>
+#include <i18n/i18n.hpp>
+#include <InputMode.hpp>
+#include <service-appmgr/Controller.hpp>
+#include <service-cellular/CellularServiceAPI.hpp>
+
+#include <cassert>
+
+namespace gui
+{
+ NumberWindow::NumberWindow(app::Application *app,
+ app::EnterNumberWindowInterface *interface,
+ std::string windowName)
+ : AppWindow(app, std::move(windowName)), interface(interface), currentCountry(defaultCountry),
+ numberUtil(*PhoneNumberUtil::GetInstance())
+ {
+ assert(interface != nullptr);
+ assert(app != nullptr);
+ switchFormatter(utils::country::getAlpha2Code(currentCountry));
+ }
+
+ void NumberWindow::setNumberLabel(const std::string &num)
+ {
+ numberLabel->setText(num);
+
+ if (num.empty()) {
+ bottomBar->setText(BottomBar::Side::RIGHT, utils::localize.get(style::strings::common::back));
+ return;
+ }
+ bottomBar->setText(BottomBar::Side::RIGHT, utils::localize.get("app_call_clear"));
+ }
+
+ void NumberWindow::buildInterface()
+ {
+ using namespace callAppStyle;
+ using namespace callAppStyle::enterNumberWindow;
+ AppWindow::buildInterface();
+
+ bottomBar->setActive(BottomBar::Side::LEFT, true);
+ bottomBar->setActive(BottomBar::Side::CENTER, true);
+ bottomBar->setActive(BottomBar::Side::RIGHT, true);
+
+ bottomBar->setText(BottomBar::Side::LEFT, utils::localize.get(callAppStyle::strings::call));
+
+ numberLabel = new gui::Label(this, numberLabel::x, numberLabel::y, numberLabel::w, numberLabel::h);
+ numberLabel->setPenWidth(numberLabel::borderW);
+ numberLabel->setFont(style::window::font::largelight);
+ numberLabel->setEdges(RectangleEdge::Bottom);
+ numberLabel->setAlignment(gui::Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Top));
+ numberLabel->setEllipsis(Ellipsis::Left);
+
+ numberDescriptionLabel = new gui::Label(this,
+ numberDescriptionLabel::x,
+ numberDescriptionLabel::y,
+ numberDescriptionLabel::w,
+ numberDescriptionLabel::h);
+ numberDescriptionLabel->setFont(style::window::font::mediumlight);
+ numberDescriptionLabel->setAlignment(
+ gui::Alignment{gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center});
+ numberDescriptionLabel->setEdges(RectangleEdge::None);
+ }
+
+ void NumberWindow::destroyInterface()
+ {
+ erase();
+ }
+
+ bool NumberWindow::onInput(const InputEvent &inputEvent)
+ {
+ auto code = translator.handle(inputEvent.key, InputMode({InputMode::phone}).get());
+ if (inputEvent.isShortPress()) {
+ // Call function
+ if (inputEvent.is(KeyCode::KEY_LF)) {
+ interface->handleCallEvent(enteredNumber);
+ return true;
+ }
+ // Clear/back function
+ else if (inputEvent.is(KeyCode::KEY_RF)) {
+ // if there isn't any char in phone number field return to previous application
+ if (enteredNumber.empty()) {
+ formatter->Clear();
+ app::manager::Controller::switchBack(application);
+ }
+ // if there is the last char just clear input
+ else if (enteredNumber.size() == 1) {
+ clearInput();
+ }
+ else {
+ // remove last digit and reformat entered number otherwise
+ enteredNumber = enteredNumber.substr(0, enteredNumber.size() - 1);
+ initFormatterInput(enteredNumber);
+ setNumberLabel(formattedNumber);
+
+ application->refreshWindow(RefreshModes::GUI_REFRESH_FAST);
+ }
+ return true;
+ }
+ else if (code != 0) {
+ addDigit(code);
+ return true;
+ }
+ }
+ else if (inputEvent.isLongPress()) {
+ // erase all characters from phone number
+ if (inputEvent.is(KeyCode::KEY_RF)) {
+ // if there isn't any char in phone number field return to previous application
+ if (enteredNumber.empty()) {
+ app::manager::Controller::switchBack(application);
+ return true;
+ }
+ clearInput();
+
+ return true;
+ }
+ // long press of '0' key is translated to '+'
+ else if (inputEvent.is(KeyCode::KEY_0)) {
+ addDigit('+');
+ return true;
+ }
+ }
+
+ // check if any of the lower inheritance onInput methods catch the event
+ return AppWindow::onInput(inputEvent);
+ }
+
+ void NumberWindow::switchFormatter(const std::string ®ionCode)
+ {
+ auto newFormatter = std::unique_ptr<Formatter>(numberUtil.GetAsYouTypeFormatter(regionCode));
+ formatter.swap(newFormatter);
+ LOG_INFO("Switched formatter to region: %s", regionCode.c_str());
+ }
+
+ void NumberWindow::initFormatterInput(const std::string &number)
+ {
+ enteredNumber = number;
+ formatter->Clear();
+ for (auto c : number) {
+ formatter->InputDigit(c, &formattedNumber);
+ }
+ }
+
+ void NumberWindow::addDigit(const std::string::value_type &digit)
+ {
+ enteredNumber += digit;
+ formatter->InputDigit(digit, &formattedNumber);
+ setNumberLabel(formattedNumber);
+ application->refreshWindow(RefreshModes::GUI_REFRESH_FAST);
+ }
+
+ const std::string &NumberWindow::getEnteredNumber() const noexcept
+ {
+ return enteredNumber;
+ }
+
+ void NumberWindow::clearInput()
+ {
+ enteredNumber.clear();
+ formattedNumber.clear();
+ formatter->Clear();
+ setNumberLabel("");
+ application->refreshWindow(RefreshModes::GUI_REFRESH_FAST);
+ }
+} /* namespace gui */
A module-apps/application-call/windows/NumberWindow.hpp => module-apps/application-call/windows/NumberWindow.hpp +62 -0
@@ 0,0 1,62 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include "application-call/ApplicationCall.hpp"
+#include "application-call/widgets/StateIcons.hpp"
+
+#include <AppWindow.hpp>
+#include <ContactRecord.hpp>
+#include <country.hpp>
+#include <gui/input/Translator.hpp>
+
+#include <phonenumbers/phonenumberutil.h>
+#include <phonenumbers/asyoutypeformatter.h>
+
+#include <memory>
+#include <string>
+
+namespace gui
+{
+ class Label;
+ class NumberWindow : public AppWindow
+ {
+ public:
+ using CountryCode = utils::country::Id;
+
+ NumberWindow(app::Application *app,
+ app::EnterNumberWindowInterface *interface,
+ std::string windowName = app::window::name_number);
+
+ auto onInput(const InputEvent &inputEvent) -> bool override;
+ [[nodiscard]] auto getEnteredNumber() const noexcept -> const std::string &;
+
+ void buildInterface() override;
+ void destroyInterface() override;
+ void initFormatterInput(const std::string &number);
+
+ protected:
+ app::EnterNumberWindowInterface *interface = nullptr;
+ gui::Label *numberLabel = nullptr;
+ gui::Label *numberDescriptionLabel = nullptr;
+ std::string formattedNumber;
+ std::string enteredNumber;
+
+ void setNumberLabel(const std::string &num);
+
+ void switchFormatter(const std::string &countryCode);
+ void addDigit(const std::string::value_type &digit);
+ void clearInput();
+
+ private:
+ using PhoneNumberUtil = i18n::phonenumbers::PhoneNumberUtil;
+ using Formatter = i18n::phonenumbers::AsYouTypeFormatter;
+
+ CountryCode defaultCountry = utils::country::defaultCountry;
+ CountryCode currentCountry;
+ gui::KeyInputMappedTranslation translator;
+ PhoneNumberUtil &numberUtil;
+ std::unique_ptr<Formatter> formatter;
+ };
+} /* namespace gui */
M module-apps/application-desktop/windows/PinLockWindow.cpp => module-apps/application-desktop/windows/PinLockWindow.cpp +2 -2
@@ 112,11 112,11 @@ namespace gui
}
// accept only LF, enter, RF, #, and numeric values;
if (inputEvent.is(KeyCode::KEY_LEFT) && iceBox->visible) {
- app::manager::Controller::sendAction(application, app::manager::actions::ShowEmergencyContacts);
+ app::manager::Controller::sendAction(application, app::manager::actions::EmergencyDial);
return true;
}
else if (inputEvent.is(KeyCode::KEY_LF) && bottomBar->isActive(BottomBar::Side::LEFT)) {
- app::manager::Controller::sendAction(application, app::manager::actions::ShowEmergencyContacts);
+ app::manager::Controller::sendAction(application, app::manager::actions::EmergencyDial);
return true;
}
else if (inputEvent.is(KeyCode::KEY_RF) && bottomBar->isActive(BottomBar::Side::RIGHT)) {
M module-apps/application-settings-new/ApplicationSettings.cpp => module-apps/application-settings-new/ApplicationSettings.cpp +22 -2
@@ 30,6 30,7 @@
#include "windows/ChangePasscodeWindow.hpp"
#include "windows/SystemMainWindow.hpp"
#include "windows/NewApnWindow.hpp"
+#include "windows/LanguagesWindow.hpp"
#include "Dialog.hpp"
@@ 42,6 43,7 @@
#include <service-db/agents/settings/SystemSettings.hpp>
#include <application-settings-new/data/ApnListData.hpp>
#include <application-settings-new/data/BondedDevicesData.hpp>
+#include <application-settings-new/data/LanguagesData.hpp>
#include <application-settings-new/data/PhoneNameData.hpp>
#include <module-services/service-db/agents/settings/SystemSettings.hpp>
#include <service-db/Settings.hpp>
@@ 49,6 51,8 @@
#include <i18n/i18n.hpp>
#include <module-services/service-evtmgr/service-evtmgr/ScreenLightControlMessage.hpp>
#include <module-services/service-evtmgr/service-evtmgr/Constants.hpp>
+#include <module-services/service-appmgr/service-appmgr/messages/Message.hpp>
+#include <module-services/service-appmgr/service-appmgr/model/ApplicationManager.hpp>
namespace app
{
@@ 158,14 162,27 @@ namespace app
return sys::MessageNone{};
});
+ connect(typeid(manager::GetCurrentDisplayLanguageResponse), [&](sys::Message *msg) {
+ if (gui::window::name::languages == getCurrentWindow()->getName()) {
+ auto response = dynamic_cast<manager::GetCurrentDisplayLanguageResponse *>(msg);
+ if (response != nullptr) {
+ auto languagesData = std::make_unique<LanguagesData>(response->getLanguage());
+ switchWindow(gui::window::name::languages, std::move(languagesData));
+ }
+ }
+ return sys::MessageNone{};
+ });
+
createUserInterface();
setActiveWindow(gui::name::window::main_window);
settings->registerValueChange(settings::operators_on,
[this](const std::string &value) { operatorOnChanged(value); });
- settings->registerValueChange(::settings::Cellular::volte_on,
- [this](const std::string &value) { volteChanged(value); });
+ settings->registerValueChange(
+ ::settings::Cellular::volte_on,
+ [this](const std::string &value) { volteChanged(value); },
+ ::settings::SettingsScope::Global);
settings->registerValueChange(
::settings::SystemProperties::lockPassHash,
[this](std::string value) { lockPassHash = utils::getNumericValue<unsigned int>(value); },
@@ 259,6 276,9 @@ namespace app
windowsFactory.attach(gui::window::name::new_apn, [](Application *app, const std::string &name) {
return std::make_unique<gui::NewApnWindow>(app);
});
+ windowsFactory.attach(gui::window::name::languages, [](Application *app, const std::string &name) {
+ return std::make_unique<gui::LanguagesWindow>(app);
+ });
}
void ApplicationSettingsNew::destroyUserInterface()
M module-apps/application-settings-new/ApplicationSettings.hpp => module-apps/application-settings-new/ApplicationSettings.hpp +1 -1
@@ 50,7 50,7 @@ namespace gui::window::name
inline constexpr auto dialog_settings = "DialogSettings";
inline constexpr auto change_passcode = "ChangePasscode";
- inline constexpr auto language = "Language";
+ inline constexpr auto languages = "Languages";
inline constexpr auto date_and_time = "DateAndTime";
inline constexpr auto factory_reset = "FactoryReset";
inline constexpr auto about_your_pure = "AboutYourPure";
M module-apps/application-settings-new/CMakeLists.txt => module-apps/application-settings-new/CMakeLists.txt +3 -0
@@ 16,6 16,7 @@ target_sources( ${PROJECT_NAME}
PRIVATE
ApplicationSettings.cpp
models/ApnSettingsModel.cpp
+ models/LanguagesModel.cpp
models/NewApnModel.cpp
widgets/timeWidget.cpp
widgets/ChangePasscodeLockHandler.cpp
@@ 50,6 51,7 @@ target_sources( ${PROJECT_NAME}
widgets/SpinBox.cpp
widgets/SpinBoxOptionSetting.cpp
windows/SystemMainWindow.cpp
+ windows/LanguagesWindow.cpp
PUBLIC
ApplicationSettings.hpp
@@ 71,6 73,7 @@ target_sources( ${PROJECT_NAME}
windows/WallpaperWindow.hpp
windows/ChangePasscodeWindow.hpp
windows/SystemMainWindow.hpp
+ windows/LanguagesWindow.hpp
)
add_dependencies(${PROJECT_NAME} version)
A module-apps/application-settings-new/data/LanguagesData.hpp => module-apps/application-settings-new/data/LanguagesData.hpp +20 -0
@@ 0,0 1,20 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <SwitchData.hpp>
+
+class LanguagesData : public gui::SwitchData
+{
+ public:
+ explicit LanguagesData(Language currentDisplayLanguage) : currentDisplayLanguage(std::move(currentDisplayLanguage))
+ {}
+ [[nodiscard]] auto getCurrentDisplayLanguage() const noexcept -> Language
+ {
+ return currentDisplayLanguage;
+ }
+
+ private:
+ Language currentDisplayLanguage;
+};
A module-apps/application-settings-new/models/LanguagesModel.cpp => module-apps/application-settings-new/models/LanguagesModel.cpp +13 -0
@@ 0,0 1,13 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include <service-appmgr/service-appmgr/messages/GetCurrentDisplayLanguageRequest.hpp>
+#include <service-appmgr/service-appmgr/model/ApplicationManager.hpp>
+#include "LanguagesModel.hpp"
+
+void LanguagesModel::requestCurrentDisplayLanguage()
+{
+ sys::Bus::SendUnicast(std::make_shared<app::manager::GetCurrentDisplayLanguageRequest>(),
+ app::manager::ApplicationManager::ServiceName,
+ application);
+}
A module-apps/application-settings-new/models/LanguagesModel.hpp => module-apps/application-settings-new/models/LanguagesModel.hpp +18 -0
@@ 0,0 1,18 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <Application.hpp>
+
+class LanguagesModel
+{
+ public:
+ explicit LanguagesModel(app::Application *application) : application(application)
+ {}
+
+ void requestCurrentDisplayLanguage();
+
+ private:
+ app::Application *application = nullptr;
+};
A module-apps/application-settings-new/windows/LanguagesWindow.cpp => module-apps/application-settings-new/windows/LanguagesWindow.cpp +67 -0
@@ 0,0 1,67 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "application-settings-new/ApplicationSettings.hpp"
+#include "application-settings-new/data/LanguagesData.hpp"
+#include "LanguagesWindow.hpp"
+#include "OptionSetting.hpp"
+#include "service-appmgr/Controller.hpp"
+
+namespace gui
+{
+ LanguagesWindow::LanguagesWindow(app::Application *app)
+ : BaseSettingsWindow(app, window::name::languages), langList(loader.getAvailableDisplayLanguages()),
+ languagesModel(app)
+ {
+ setTitle(utils::localize.get("app_settings_title_languages"));
+ languagesModel.requestCurrentDisplayLanguage();
+ }
+
+ void LanguagesWindow::addOptions(std::list<Option> &optionList)
+ {
+ OptionWindow::addOptions(optionList);
+ optionsList->setFocusOnElement(selectedLanguageIndex);
+ }
+
+ auto LanguagesWindow::buildOptionsList() -> std::list<gui::Option>
+ {
+ std::list<gui::Option> options;
+
+ for (const auto &lang : langList) {
+ options.emplace_back(std::make_unique<gui::option::OptionSettings>(
+ lang,
+ [=](const gui::Item &item) {
+ app::manager::Controller::changeDisplayLanguage(application, lang);
+ return true;
+ },
+ nullptr,
+ this,
+ selectedLanguage == lang ? gui::option::SettingRightItem::Checked
+ : gui::option::SettingRightItem::Disabled));
+ }
+
+ return options;
+ }
+
+ auto LanguagesWindow::handleSwitchData(SwitchData *data) -> bool
+ {
+ auto *languagesData = dynamic_cast<LanguagesData *>(data);
+ if (languagesData == nullptr) {
+ return false;
+ }
+ selectedLanguage = languagesData->getCurrentDisplayLanguage();
+ setLanguageIndex();
+
+ return true;
+ }
+
+ void LanguagesWindow::setLanguageIndex()
+ {
+ for (unsigned int langIndex = 0; langIndex < langList.size(); ++langIndex) {
+ if (selectedLanguage == langList[langIndex]) {
+ selectedLanguageIndex = langIndex;
+ break;
+ }
+ }
+ }
+} /* namespace gui */
A module-apps/application-settings-new/windows/LanguagesWindow.hpp => module-apps/application-settings-new/windows/LanguagesWindow.hpp +29 -0
@@ 0,0 1,29 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include "application-settings-new/models/LanguagesModel.hpp"
+#include "BaseSettingsWindow.hpp"
+#include <i18n/i18n.hpp>
+
+namespace gui
+{
+ class LanguagesWindow : public BaseSettingsWindow
+ {
+ public:
+ explicit LanguagesWindow(app::Application *app);
+
+ private:
+ void addOptions(std::list<Option> &optionList) override;
+ auto buildOptionsList() -> std::list<Option> override;
+ auto handleSwitchData(SwitchData *data) -> bool override;
+ void setLanguageIndex();
+
+ utils::LangLoader loader;
+ const std::vector<Language> langList;
+ LanguagesModel languagesModel;
+ Language selectedLanguage;
+ unsigned int selectedLanguageIndex{0};
+ };
+} /* namespace gui */
M module-apps/application-settings-new/windows/SystemMainWindow.cpp => module-apps/application-settings-new/windows/SystemMainWindow.cpp +1 -1
@@ 26,7 26,7 @@ namespace gui
option::SettingRightItem::ArrowWhite));
};
- addOption("app_settings_language", gui::window::name::language);
+ addOption("app_settings_language", gui::window::name::languages);
addOption("app_settings_date_and_time", gui::window::name::date_and_time);
addOption("app_settings_factory_reset", gui::window::name::factory_reset);
addOption("app_settings_about_your_pure", gui::window::name::about_your_pure);
M module-apps/windows/OptionWindow.hpp => module-apps/windows/OptionWindow.hpp +1 -1
@@ 23,7 23,7 @@ namespace gui
std::shared_ptr<OptionsModel> optionsModel = nullptr;
ListView *optionsList = nullptr;
std::list<Option> options;
- void addOptions(std::list<Option> &optionList);
+ virtual void addOptions(std::list<Option> &optionList);
void addOptions(std::list<Option> &&optionList);
void resetOptions(std::list<Option> &&optionList);
M module-bsp/board/linux/eink/ED028TC1.c => module-bsp/board/linux/eink/ED028TC1.c +1 -1
@@ 129,7 129,7 @@ EinkStatus_e EinkResetAndInitialize()
return EinkOK;
}
-EinkStatus_e EinkUpdateWaveform(const EinkWaveFormSettings_t *settings)
+EinkStatus_e EinkUpdateWaveform(const EinkWaveformSettings_t *settings)
{
return EinkOK;
}
M module-bsp/board/linux/eink/ED028TC1.h => module-bsp/board/linux/eink/ED028TC1.h +4 -2
@@ 297,6 297,8 @@ extern "C"
EinkWaveforms_e mode;
// temperature of surrounding
int32_t temperature;
+ // use counter to keep track if need to change
+ uint32_t useCounter;
// pointer to lookup table for lut c
uint8_t *LUTCData;
// sizeo of lutc data
@@ 305,7 307,7 @@ extern "C"
uint8_t *LUTDData;
// size of lutd data
uint32_t LUTDSize;
- } EinkWaveFormSettings_t;
+ } EinkWaveformSettings_t;
/* Exported constants --------------------------------------------------------*/
@@ 419,7 421,7 @@ extern "C"
* @param LUTCData [in] - Data
* @return
*/
- EinkStatus_e EinkUpdateWaveform(const EinkWaveFormSettings_t *settings);
+ EinkStatus_e EinkUpdateWaveform(const EinkWaveformSettings_t *settings);
/**
* This function converts the ARGB image to the L4 format
M module-bsp/board/rt1051/bsp/eink/ED028TC1.cpp => module-bsp/board/rt1051/bsp/eink/ED028TC1.cpp +8 -17
@@ 65,8 65,6 @@
#define _delay_ms(ms) vTaskDelay(pdMS_TO_TICKS(ms))
-#define EINK_SUSPEND_TASK_TILL_EPD_BUSY() BSP_EinkWaitUntilDisplayBusy(pdMS_TO_TICKS(1000))
-
//#define EINK_DEBUG_LOG 1
//
//#if EINK_DEBUG_LOG == 1
@@ 81,14 79,11 @@ using namespace magic_enum;
static std::shared_ptr<drivers::DriverDMA> dma;
static std::shared_ptr<drivers::DriverDMAMux> dmamux;
-#define EINK_LUTS_FILE_PATH "/Luts.bin"
-
/* Internal variable definitions */
static uint8_t s_einkIsPoweredOn = false; // Variable which contains the state of the power of the EPD display
static EinkWaveforms_e s_einkConfiguredWaveform =
EinkWaveformGC16; // This variable contains the current waveform set in the display
-static int8_t s_einkPreviousTemperature = 127; // This variable contains the last measured temperature of the ambient
static CACHEABLE_SECTION_SDRAM(uint8_t s_einkServiceRotatedBuf[BOARD_EINK_DISPLAY_RES_X * BOARD_EINK_DISPLAY_RES_Y / 2 +
2]); // Plus 2 for the EPD command and BPP config
@@ 548,7 543,7 @@ void EinkPowerOn()
return;
}
- EINK_SUSPEND_TASK_TILL_EPD_BUSY();
+ BSP_EinkWaitUntilDisplayBusy(pdMS_TO_TICKS(BSP_EinkBusyTimeout));
s_einkIsPoweredOn = true;
}
}
@@ 563,7 558,7 @@ void EinkPowerOff()
return;
}
- EINK_SUSPEND_TASK_TILL_EPD_BUSY();
+ BSP_EinkWaitUntilDisplayBusy(pdMS_TO_TICKS(BSP_EinkBusyTimeout));
s_einkIsPoweredOn = false;
}
}
@@ 590,7 585,7 @@ int16_t EinkGetTemperatureInternal()
return -1;
}
- EINK_SUSPEND_TASK_TILL_EPD_BUSY();
+ BSP_EinkWaitUntilDisplayBusy(pdMS_TO_TICKS(BSP_EinkBusyTimeout));
if (BSP_EinkReadData(temp, sizeof(temp), SPI_MANUAL_CS) != 0) {
// LOG_ERROR("Requesting the temperature FAILED");
@@ 641,8 636,8 @@ static void s_EinkSetInitialConfig()
}
tmpbuf[0] = EinkPanelSetting; // 0x00
- tmpbuf[1] = LUT_SEL | SHL | RST_N; // 0x25 -> _XON _RES0 LUT_SEL _DM - SHL _SPIWM RST_N // If 0x35 (DM - 1 is used
- // (2bpp)) the SPI speed can be 25MHz
+ tmpbuf[1] = LUT_SEL | SHL | RST_N; // 0x25 -> _XON _RES0 LUT_SEL _DM - SHL _SPIWM RST_N
+ // If 0x35 (DM - 1 is used (2bpp)) the SPI speed can be 25MHz
tmpbuf[2] = 0x00;
if (BSP_EinkWriteData(tmpbuf, 3, SPI_AUTOMATIC_CS) != 0) {
// LOG_ERROR("Setting the initial configuration for the Eink failed");
@@ 747,13 742,9 @@ EinkStatus_e EinkResetAndInitialize()
return EinkOK;
}
-EinkStatus_e EinkUpdateWaveform(const EinkWaveFormSettings_t *settings)
+EinkStatus_e EinkUpdateWaveform(const EinkWaveformSettings_t *settings)
{
- // If neither the temperature nor the waveform has changed - do nothing
- if ((settings->temperature == s_einkPreviousTemperature) && (settings->mode == s_einkConfiguredWaveform)) {
- return EinkOK;
- }
-
+ /// LUTD
if (BSP_EinkWriteData(settings->LUTDData, settings->LUTDSize, SPI_AUTOMATIC_CS) != 0) {
EinkResetAndInitialize();
return EinkSPIErr;
@@ 1015,7 1006,7 @@ EinkStatus_e EinkRefreshImage(
return EinkSPIErr;
}
- EINK_SUSPEND_TASK_TILL_EPD_BUSY();
+ BSP_EinkWaitUntilDisplayBusy(pdMS_TO_TICKS(BSP_EinkBusyTimeout));
return EinkOK;
}
M module-bsp/board/rt1051/bsp/eink/ED028TC1.h => module-bsp/board/rt1051/bsp/eink/ED028TC1.h +4 -2
@@ 297,6 297,8 @@ extern "C"
EinkWaveforms_e mode;
// temperature of surrounding
int32_t temperature;
+ // counts usage of this waveform (display refreshes)
+ uint32_t useCounter;
// pointer to lookup table for lut c
uint8_t *LUTCData;
// sizeo of lutc data
@@ 305,7 307,7 @@ extern "C"
uint8_t *LUTDData;
// size of lutd data
uint32_t LUTDSize;
- } EinkWaveFormSettings_t;
+ } EinkWaveformSettings_t;
/* Exported constants --------------------------------------------------------*/
@@ 419,7 421,7 @@ extern "C"
* @param LUTCData [in] - Data
* @return
*/
- EinkStatus_e EinkUpdateWaveform(const EinkWaveFormSettings_t *settings);
+ EinkStatus_e EinkUpdateWaveform(const EinkWaveformSettings_t *settings);
/**
* This function converts the ARGB image to the L4 format
M module-bsp/board/rt1051/bsp/eink/bsp_eink.h => module-bsp/board/rt1051/bsp/eink/bsp_eink.h +1 -1
@@ 33,7 33,7 @@ extern "C"
typedef void (*bsp_eink_BusyEvent)(void);
-#define BSP_EINK_TRANSFER_TIMEOUT_MS 1000
+ inline constexpr auto BSP_EinkBusyTimeout = 3000U;
status_t BSP_EinkInit(bsp_eink_BusyEvent event);
void BSP_EinkDeinit(void);
M module-cellular/at/ErrorCode.hpp => module-cellular/at/ErrorCode.hpp +1 -1
@@ 54,6 54,7 @@ namespace at
ServiceProvPersPUKRequired = 45,
CorporatePersPINRequired = 46,
CorporatePersPUKRequired = 47,
+ PhoneBusy = 258,
AudioUnknownError = 901,
AudioInvalidParameters = 902,
AudioOperationNotSupported = 903,
@@ 69,7 70,6 @@ namespace at
*/
enum class NetworkErrorCode : uint32_t
{
-
MEFailure = 300,
SMS_MEReserved = 301,
OperationNotAllowed = 302,
M module-cellular/at/response.cpp => module-cellular/at/response.cpp +204 -0
@@ 424,5 424,209 @@ namespace at
return message;
}
} // namespace clir
+
+ namespace ccfc
+ {
+
+ auto parse(std::vector<std::string> response, std::vector<ParsedCcfc> &parsed) -> bool
+ {
+
+ auto constexpr toRemove = "+CCFC: ";
+ auto constexpr emptyString = "";
+ auto constexpr quote = "\"";
+
+ parsed.clear();
+
+ for (auto el : response) {
+
+ if (el.find("OK") != std::string::npos) {
+ return true;
+ }
+
+ utils::findAndReplaceAll(el, toRemove, emptyString);
+ auto tokens = utils::split(el, ",");
+
+ if (tokens.size() == serviceDisabledTokenCount) {
+ parsed.push_back(ParsedCcfc(ConnectionClass::None, ForwardingStatus::NotActive, ""));
+ }
+ else if (tokens.size() > serviceDisabledTokenCount) {
+ int statusToken = 0;
+ int connectionClassToken = 0;
+
+ if (!utils::toNumeric(tokens[Tokens::Status], statusToken) ||
+ !utils::toNumeric(tokens[Tokens::Class], connectionClassToken)) {
+ return false;
+ }
+ auto status = static_cast<ForwardingStatus>(statusToken);
+ auto connectionClass = static_cast<ConnectionClass>(connectionClassToken);
+
+ if (magic_enum::enum_contains<ForwardingStatus>(status) &&
+ magic_enum::enum_contains<ConnectionClass>(connectionClass)) {
+ auto number = tokens[Tokens::Number];
+ utils::findAndReplaceAll(number, quote, emptyString);
+ utils::trim(number);
+ parsed.push_back(ParsedCcfc(connectionClass, status, number));
+ }
+ else {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ auto getNumbers(std::vector<ParsedCcfc> &parsed) -> CcfcNumbers
+ {
+ CcfcNumbers numbers;
+
+ for (auto el : parsed) {
+ std::string number = "";
+ if (el.status == ForwardingStatus::Active) {
+ number = el.number;
+ }
+ switch (el.connectionClass) {
+ case ConnectionClass::None:
+ break;
+ case ConnectionClass::Voice:
+ numbers.voice = number;
+ break;
+ case ConnectionClass::Data:
+ break;
+ case ConnectionClass::Fax:
+ numbers.fax = number;
+ break;
+ case ConnectionClass::AllTelephonyExceptSMS:
+ break;
+ case ConnectionClass::ShortMessgeService:
+ break;
+ case ConnectionClass::DataAsync:
+ numbers.async = number;
+ break;
+ case ConnectionClass::DataSync:
+ numbers.sync = number;
+ break;
+ }
+ }
+ return numbers;
+ }
+
+ auto isAnyActive(std::vector<ParsedCcfc> &parsed) -> bool
+ {
+ for (auto el : parsed) {
+ if (el.status == ForwardingStatus::Active) {
+ return true;
+ }
+ }
+ return false;
+ }
+ } // namespace ccfc
+
+ namespace mmi
+ {
+ auto getClass(const ServiceClass &serviceClass) noexcept
+ -> app::manager::actions::IMMICustomResultParams::MMIResultMessage
+ {
+ using namespace app::manager::actions;
+
+ auto message = IMMICustomResultParams::MMIResultMessage::CommonNoMessage;
+ switch (serviceClass) {
+ case ServiceClass::Voice:
+ message = IMMICustomResultParams::MMIResultMessage::CommonVoice;
+ break;
+ case ServiceClass::Data:
+ message = IMMICustomResultParams::MMIResultMessage::CommonData;
+ break;
+ case ServiceClass::Fax:
+ message = IMMICustomResultParams::MMIResultMessage::CommonFax;
+ break;
+ case ServiceClass::DataSync:
+ message = IMMICustomResultParams::MMIResultMessage::CommonSync;
+ break;
+ case ServiceClass::DataAsync:
+ message = IMMICustomResultParams::MMIResultMessage::CommonAsync;
+ break;
+ case ServiceClass::AllDisabled:
+ message = IMMICustomResultParams::MMIResultMessage::CommonAllDisabled;
+ break;
+ }
+ return message;
+ }
+ } // namespace mmi
+
+ namespace clck
+ {
+ auto parseQueryResponse(const std::vector<std::string> &data, std::vector<ClckParsed> &parsed) -> bool
+ {
+ using namespace mmi;
+
+ auto constexpr responseToken = "+CLCK: ";
+ auto constexpr emptyString = "";
+ auto constexpr minTokens = 2;
+ parsed.clear();
+
+ for (auto el : data) {
+ if (el.find("OK") != std::string::npos) {
+ return true;
+ }
+ if (el.find(responseToken) == std::string::npos) {
+ parsed.clear();
+ return false;
+ }
+ utils::findAndReplaceAll(el, responseToken, emptyString);
+ auto tokens = utils::split(el, ",");
+ if (tokens.size() < minTokens) {
+ parsed.clear();
+ return false;
+ }
+ for (auto &t : tokens) {
+ t = utils::trim(t);
+ }
+
+ int statusToken = 0;
+ int serviceClassToken = 0;
+
+ if (!utils::toNumeric(tokens[0], statusToken) || !utils::toNumeric(tokens[1], serviceClassToken)) {
+ return false;
+ }
+ auto status = static_cast<Status>(statusToken);
+ auto serviceClass = static_cast<ServiceClass>(serviceClassToken);
+
+ if (magic_enum::enum_contains<Status>(status) &&
+ magic_enum::enum_contains<ServiceClass>(serviceClass)) {
+ parsed.push_back(ClckParsed(status, serviceClass));
+ }
+ else {
+ parsed.clear();
+ return false;
+ }
+ }
+ return true;
+ }
+
+ auto iterLessIter(ClckParsed a, ClckParsed b) -> bool
+ {
+ return a.serviceClass < b.serviceClass;
+ }
+
+ auto getStatus(const Status &status) noexcept
+ -> app::manager::actions::IMMICustomResultParams::MMIResultMessage
+ {
+ using namespace app::manager::actions;
+
+ auto message = IMMICustomResultParams::MMIResultMessage::CommonNoMessage;
+ switch (status) {
+ case Status::Disable:
+ message = IMMICustomResultParams::MMIResultMessage::CommonDeactivated;
+ break;
+ case Status::Enable:
+ message = IMMICustomResultParams::MMIResultMessage::CommonActivated;
+ break;
+ case Status::Query:
+ message = IMMICustomResultParams::MMIResultMessage::CommonQuery;
+ break;
+ }
+ return message;
+ }
+ } // namespace clck
} // namespace response
} // namespace at
M module-cellular/at/response.hpp => module-cellular/at/response.hpp +96 -0
@@ 278,5 278,101 @@ namespace at
auto getStatus(const ServiceStatus &status)
-> app::manager::actions::IMMICustomResultParams::MMIResultMessage;
} // namespace clir
+
+ namespace ccfc
+ {
+
+ enum class ConnectionClass
+ {
+ None = 0,
+ Voice = 1,
+ Data = 2,
+ Fax = 4,
+ AllTelephonyExceptSMS = 7,
+ ShortMessgeService = 8,
+ DataAsync = 16,
+ DataSync = 32
+ };
+
+ enum class ForwardingStatus
+ {
+ NotActive,
+ Active
+ };
+
+ struct ParsedCcfc
+ {
+ ConnectionClass connectionClass;
+ ForwardingStatus status;
+ std::string number;
+
+ explicit ParsedCcfc(ConnectionClass connectionClass, ForwardingStatus status, const std::string &number)
+ : connectionClass(connectionClass), status(status), number(number)
+ {}
+ };
+
+ enum Tokens
+ {
+ Status,
+ Class,
+ Number,
+ Type
+ };
+
+ struct CcfcNumbers
+ {
+ std::string voice;
+ std::string fax;
+ std::string sync;
+ std::string async;
+ };
+
+ auto constexpr serviceDisabledTokenCount = 2;
+ auto constexpr serviceEnabledTokenCount = 4;
+
+ auto parse(std::vector<std::string> response, std::vector<ParsedCcfc> &parsed) -> bool;
+ auto getNumbers(std::vector<ParsedCcfc> &parsed) -> CcfcNumbers;
+ auto isAnyActive(std::vector<ParsedCcfc> &parsed) -> bool;
+ } // namespace ccfc
+
+ namespace mmi
+ {
+
+ enum class ServiceClass
+ {
+ Voice = 1,
+ Data = 2,
+ Fax = 4,
+ DataSync = 16,
+ DataAsync = 32,
+ AllDisabled = 255
+ };
+
+ auto getClass(const ServiceClass &serviceClass) noexcept
+ -> app::manager::actions::IMMICustomResultParams::MMIResultMessage;
+ } // namespace mmi
+
+ namespace clck
+ {
+ enum class Status
+ {
+ Disable,
+ Enable,
+ Query
+ };
+
+ struct ClckParsed
+ {
+ Status status;
+ mmi::ServiceClass serviceClass;
+ explicit ClckParsed(Status status, mmi::ServiceClass serviceClass)
+ : status(status), serviceClass(serviceClass){};
+ };
+
+ auto parseQueryResponse(const std::vector<std::string> &data, std::vector<ClckParsed> &parsed) -> bool;
+ auto iterLessIter(ClckParsed a, ClckParsed b) -> bool;
+ auto getStatus(const Status &status) noexcept
+ -> app::manager::actions::IMMICustomResultParams::MMIResultMessage;
+ } // namespace clck
} // namespace response
} // namespace at
M module-cellular/test/unittest_response.cpp => module-cellular/test/unittest_response.cpp +116 -0
@@ 152,3 152,119 @@ TEST_CASE("Response COPS")
REQUIRE(at::response::parseCOPS(resp, ret) == false);
}
}
+
+TEST_CASE("Response CLCK")
+{
+ SECTION("OK CLCK QUERY - all disabled")
+ {
+
+ at::Result resp;
+ resp.code = at::Result::Code::OK;
+ std::vector<at::response::clck::ClckParsed> ret;
+ resp.response.push_back("+CLCK: 0,255");
+ resp.response.push_back("OK");
+
+ REQUIRE(resp.code == at::Result::Code::OK);
+ REQUIRE(at::response::clck::parseQueryResponse(resp.response, ret) == true);
+ REQUIRE(ret.size() == 1);
+ REQUIRE(ret[0].status == at::response::clck::Status::Disable);
+ REQUIRE(ret[0].serviceClass == at::response::mmi::ServiceClass::AllDisabled);
+ }
+
+ SECTION("OK CLCK QUERY - voice enabled")
+ {
+
+ at::Result resp;
+ resp.code = at::Result::Code::OK;
+ std::vector<at::response::clck::ClckParsed> ret;
+ resp.response.push_back("+CLCK: 1,1");
+ resp.response.push_back("OK");
+
+ REQUIRE(resp.code == at::Result::Code::OK);
+ REQUIRE(at::response::clck::parseQueryResponse(resp.response, ret) == true);
+ REQUIRE(ret.size() == 1);
+ REQUIRE(ret[0].status == at::response::clck::Status::Enable);
+ REQUIRE(ret[0].serviceClass == at::response::mmi::ServiceClass::Voice);
+ }
+
+ SECTION("OK CLCK QUERY - voice, fax enabled")
+ {
+
+ at::Result resp;
+ resp.code = at::Result::Code::OK;
+ std::vector<at::response::clck::ClckParsed> ret;
+ resp.response.push_back("+CLCK: 1,1");
+ resp.response.push_back("+CLCK: 1,4");
+ resp.response.push_back("OK");
+
+ REQUIRE(resp.code == at::Result::Code::OK);
+ REQUIRE(at::response::clck::parseQueryResponse(resp.response, ret) == true);
+ REQUIRE(ret.size() == 2);
+
+ REQUIRE(ret[0].status == at::response::clck::Status::Enable);
+ REQUIRE(ret[0].serviceClass == at::response::mmi::ServiceClass::Voice);
+
+ REQUIRE(ret[1].status == at::response::clck::Status::Enable);
+ REQUIRE(ret[1].serviceClass == at::response::mmi::ServiceClass::Fax);
+ }
+
+ SECTION("WRONG CLCK QUERY - invalid status")
+ {
+
+ at::Result resp;
+ resp.code = at::Result::Code::OK;
+ std::vector<at::response::clck::ClckParsed> ret;
+ resp.response.push_back("+CLCK: 8,1");
+ resp.response.push_back("+CLCK: 1,4");
+ resp.response.push_back("OK");
+
+ REQUIRE(resp.code == at::Result::Code::OK);
+ REQUIRE(at::response::clck::parseQueryResponse(resp.response, ret) == false);
+ REQUIRE(ret.size() == 0);
+ }
+
+ SECTION("WRONG CLCK QUERY - invalid class")
+ {
+
+ at::Result resp;
+ resp.code = at::Result::Code::OK;
+ std::vector<at::response::clck::ClckParsed> ret;
+ resp.response.push_back("+CLCK: 1,1");
+ resp.response.push_back("+CLCK: 1,99");
+ resp.response.push_back("OK");
+
+ REQUIRE(resp.code == at::Result::Code::OK);
+ REQUIRE(at::response::clck::parseQueryResponse(resp.response, ret) == false);
+ REQUIRE(ret.size() == 0);
+ }
+
+ SECTION("WRONG CLCK QUERY - too short")
+ {
+
+ at::Result resp;
+ resp.code = at::Result::Code::OK;
+ std::vector<at::response::clck::ClckParsed> ret;
+ resp.response.push_back("+CLCK: 1");
+ resp.response.push_back("+CLCK: 1,4");
+ resp.response.push_back("OK");
+
+ REQUIRE(resp.code == at::Result::Code::OK);
+ REQUIRE(at::response::clck::parseQueryResponse(resp.response, ret) == false);
+ REQUIRE(ret.size() == 0);
+ }
+
+ SECTION("WRONG CLCK QUERY - invalid response token")
+ {
+
+ at::Result resp;
+ resp.code = at::Result::Code::OK;
+ std::vector<at::response::clck::ClckParsed> ret;
+ resp.response.push_back("+CLC: 1,1");
+ resp.response.push_back("+CLCK: 1,4");
+ resp.response.push_back("OK");
+
+ REQUIRE(resp.code == at::Result::Code::OK);
+ REQUIRE(at::response::clck::parseQueryResponse(resp.response, ret) == false);
+ REQUIRE(ret.size() == 0);
+ }
+}
M module-db/CMakeLists.txt => module-db/CMakeLists.txt +1 -0
@@ 111,6 111,7 @@ set(SOURCES
queries/calendar/QueryEventsEditICS.cpp
queries/calendar/QueryEventsEdit.cpp
queries/calendar/QueryEventsGetFiltered.cpp
+ queries/calendar/QueryEventsGetFilteredByDay.cpp
queries/calendar/QueryEventsGetAllLimited.cpp
queries/calendar/QueryEventsSelectFirstUpcoming.cpp
queries/alarms/QueryAlarmsAdd.cpp
M module-db/Interface/AlarmsRecord.hpp => module-db/Interface/AlarmsRecord.hpp +1 -1
@@ 28,7 28,7 @@ namespace db::query::alarms
struct AlarmsRecord : public Record
{
- calendar::TimePoint time = TIME_POINT_INVALID;
+ TimePoint time = TIME_POINT_INVALID;
uint32_t snooze = 0;
AlarmStatus status = AlarmStatus::On;
uint32_t repeat = 0;
M module-db/Interface/EventsRecord.cpp => module-db/Interface/EventsRecord.cpp +44 -8
@@ 10,6 10,7 @@
#include "module-db/queries/calendar/QueryEventsEdit.hpp"
#include <module-db/queries/calendar/QueryEventsEditICS.hpp>
#include <module-db/queries/calendar/QueryEventsGetFiltered.hpp>
+#include <module-db/queries/calendar/QueryEventsGetFilteredByDay.hpp>
#include <module-db/queries/calendar/QueryEventsGetAllLimited.hpp>
#include <module-db/queries/calendar/QueryEventsSelectFirstUpcoming.hpp>
#include <log/log.hpp>
@@ 70,8 71,8 @@ bool EventsRecordInterface::Add(const EventsRecord &rec)
return false;
}
-std::vector<EventsRecord> EventsRecordInterface::Select(calendar::TimePoint filter_from,
- calendar::TimePoint filter_till,
+std::vector<EventsRecord> EventsRecordInterface::Select(TimePoint filter_from,
+ TimePoint filter_till,
uint32_t offset,
uint32_t limit)
{
@@ 86,6 87,19 @@ std::vector<EventsRecord> EventsRecordInterface::Select(calendar::TimePoint filt
return records;
}
+std::vector<EventsRecord> EventsRecordInterface::Select(TimePoint date, uint32_t offset, uint32_t limit)
+{
+ auto rows = eventsDb->events.selectByDate(date, offset, limit);
+
+ auto records = std::vector<EventsRecord>();
+
+ for (auto &r : rows) {
+ records.push_back(r);
+ }
+
+ return records;
+}
+
std::unique_ptr<std::vector<EventsRecord>> EventsRecordInterface::GetLimitOffsetByField(uint32_t offset,
uint32_t limit,
EventsRecordField field,
@@ 265,13 279,17 @@ uint32_t EventsRecordInterface::GetCount()
return eventsDb->events.count();
}
-uint32_t EventsRecordInterface::GetCountFiltered(calendar::TimePoint from, calendar::TimePoint till)
+uint32_t EventsRecordInterface::GetCountFiltered(TimePoint from, TimePoint till)
{
return eventsDb->events.countFromFilter(from, till);
}
-std::vector<EventsRecord> EventsRecordInterface::SelectFirstUpcoming(calendar::TimePoint filter_from,
- calendar::TimePoint filter_till)
+uint32_t EventsRecordInterface::GetCountFilteredByDay(TimePoint filter)
+{
+ return eventsDb->events.countFromDayFilter(filter);
+}
+
+std::vector<EventsRecord> EventsRecordInterface::SelectFirstUpcoming(TimePoint filter_from, TimePoint filter_till)
{
auto rows = eventsDb->events.SelectFirstUpcoming(filter_from, filter_till);
@@ 297,6 315,9 @@ std::unique_ptr<db::QueryResult> EventsRecordInterface::runQuery(std::shared_ptr
if (typeid(*query) == typeid(db::query::events::GetFiltered)) {
return runQueryImplGetFilteredResult(query);
}
+ if (typeid(*query) == typeid(db::query::events::GetFilteredByDay)) {
+ return runQueryImplGetFilteredByDayResult(query);
+ }
if (typeid(*query) == typeid(db::query::events::Add)) {
return runQueryImplAdd(query);
}
@@ 354,12 375,27 @@ std::unique_ptr<db::query::events::GetFilteredResult> EventsRecordInterface::run
std::shared_ptr<db::Query> query)
{
auto getFilteredQuery = static_cast<db::query::events::GetFiltered *>(query.get());
- auto records = Select(getFilteredQuery->filter_from,
+
+ auto records = Select(getFilteredQuery->filter_from,
getFilteredQuery->filter_till,
getFilteredQuery->offset,
getFilteredQuery->limit);
- auto numberOfEvents = GetCountFiltered(getFilteredQuery->filter_from, getFilteredQuery->filter_till);
- auto response = std::make_unique<db::query::events::GetFilteredResult>(std::move(records), numberOfEvents);
+
+ auto numberOfEvents = GetCountFiltered(getFilteredQuery->filter_from, getFilteredQuery->filter_till);
+ auto response = std::make_unique<db::query::events::GetFilteredResult>(std::move(records), numberOfEvents);
+ response->setRequestQuery(query);
+ return response;
+}
+
+std::unique_ptr<db::query::events::GetFilteredByDayResult> EventsRecordInterface::runQueryImplGetFilteredByDayResult(
+ std::shared_ptr<db::Query> query)
+{
+ auto getFilteredQuery = static_cast<db::query::events::GetFilteredByDay *>(query.get());
+
+ auto records = Select(getFilteredQuery->filterDate, getFilteredQuery->offset, getFilteredQuery->limit);
+
+ auto numberOfEvents = GetCountFilteredByDay(getFilteredQuery->filterDate);
+ auto response = std::make_unique<db::query::events::GetFilteredByDayResult>(std::move(records), numberOfEvents);
response->setRequestQuery(query);
return response;
}
M module-db/Interface/EventsRecord.hpp => module-db/Interface/EventsRecord.hpp +12 -9
@@ 23,6 23,8 @@ namespace db::query::events
class GetAllLimitedResult;
class GetFiltered;
class GetFilteredResult;
+ class GetFilteredByDay;
+ class GetFilteredByDayResult;
class Add;
class AddResult;
class Remove;
@@ 41,11 43,11 @@ struct EventsRecord : public Record
{
std::string UID;
std::string title;
- calendar::TimePoint date_from;
- calendar::TimePoint date_till;
+ TimePoint date_from;
+ TimePoint date_till;
uint32_t reminder = 0;
uint32_t repeat = 0;
- calendar::TimePoint reminder_fired;
+ TimePoint reminder_fired;
std::string provider_type;
std::string provider_id;
std::string provider_iCalUid;
@@ 77,18 79,17 @@ class EventsRecordInterface : public RecordInterface<EventsRecord, EventsRecordF
EventsRecord GetByID(uint32_t id) override final;
EventsRecord GetByUID(const std::string &uid);
uint32_t GetCount() override final;
- uint32_t GetCountFiltered(calendar::TimePoint from, calendar::TimePoint till);
- std::vector<EventsRecord> Select(calendar::TimePoint filter_from,
- calendar::TimePoint filter_till,
- uint32_t offset,
- uint32_t limit);
+ uint32_t GetCountFiltered(TimePoint from, TimePoint till);
+ uint32_t GetCountFilteredByDay(TimePoint filter);
+ std::vector<EventsRecord> Select(TimePoint filter_from, TimePoint filter_till, uint32_t offset, uint32_t limit);
+ std::vector<EventsRecord> Select(TimePoint date, uint32_t offset, uint32_t limit);
std::unique_ptr<std::vector<EventsRecord>> GetLimitOffset(uint32_t offset, uint32_t limit) override final;
std::unique_ptr<std::vector<EventsRecord>> GetLimitOffsetByField(uint32_t offset,
uint32_t limit,
EventsRecordField field,
const char *str) override final;
std::vector<EventsRecord> GetLimitOffsetByDate(uint32_t offset, uint32_t limit);
- std::vector<EventsRecord> SelectFirstUpcoming(calendar::TimePoint filter_from, calendar::TimePoint filter_till);
+ std::vector<EventsRecord> SelectFirstUpcoming(TimePoint filter_from, TimePoint filter_till);
std::unique_ptr<db::QueryResult> runQuery(std::shared_ptr<db::Query> query) override;
@@ 101,6 102,8 @@ class EventsRecordInterface : public RecordInterface<EventsRecord, EventsRecordF
std::shared_ptr<db::Query> query);
std::unique_ptr<db::query::events::GetFilteredResult> runQueryImplGetFilteredResult(
std::shared_ptr<db::Query> query);
+ std::unique_ptr<db::query::events::GetFilteredByDayResult> runQueryImplGetFilteredByDayResult(
+ std::shared_ptr<db::Query> query);
std::unique_ptr<db::query::events::AddResult> runQueryImplAdd(std::shared_ptr<db::Query> query);
std::unique_ptr<db::query::events::RemoveResult> runQueryImplRemove(std::shared_ptr<db::Query> query);
std::unique_ptr<db::query::events::RemoveICSResult> runQueryImplRemoveICS(std::shared_ptr<db::Query> query);
M module-db/Tables/AlarmsTable.cpp => module-db/Tables/AlarmsTable.cpp +1 -1
@@ 9,7 9,7 @@ AlarmsTableRow::AlarmsTableRow(const AlarmsRecord &rec)
{}
AlarmsTableRow::AlarmsTableRow(
- uint32_t id, calendar::TimePoint time, uint32_t snooze, AlarmStatus status, uint32_t repeat, UTF8 path)
+ uint32_t id, TimePoint time, uint32_t snooze, AlarmStatus status, uint32_t repeat, UTF8 path)
: Record{id}, time{time}, snooze{snooze}, status{status}, repeat{repeat}, path{std::move(path)}
{}
M module-db/Tables/AlarmsTable.hpp => module-db/Tables/AlarmsTable.hpp +2 -3
@@ 25,15 25,14 @@ enum class AlarmStatus
struct AlarmsTableRow : public Record
{
- calendar::TimePoint time = TIME_POINT_INVALID;
+ TimePoint time = TIME_POINT_INVALID;
uint32_t snooze = 0;
AlarmStatus status = AlarmStatus::On;
uint32_t repeat = 0;
UTF8 path;
AlarmsTableRow() = default;
- AlarmsTableRow(
- uint32_t id, calendar::TimePoint time, uint32_t snooze, AlarmStatus status, uint32_t repeat, UTF8 path);
+ AlarmsTableRow(uint32_t id, TimePoint time, uint32_t snooze, AlarmStatus status, uint32_t repeat, UTF8 path);
explicit AlarmsTableRow(const AlarmsRecord &rec);
explicit AlarmsTableRow(const QueryResult &result);
};
M module-db/Tables/EventsTable.cpp => module-db/Tables/EventsTable.cpp +70 -13
@@ 643,17 643,61 @@ EventsTableRow EventsTable::getByUID(const std::string &UID)
};
}
-std::vector<EventsTableRow> EventsTable::selectByDatePeriod(calendar::TimePoint date_filter,
- calendar::TimePoint filter_till,
+std::vector<EventsTableRow> EventsTable::selectByDatePeriod(TimePoint filterFrom,
+ TimePoint filterTill,
uint32_t offset,
uint32_t limit)
{
- auto retQuery = db->query("SELECT * FROM events WHERE date_from >= date('%q') AND date_from < date('%q', 'start of "
- "day') ORDER BY datetime(date_from) LIMIT %u OFFSET %u;",
- TimePointToString(date_filter).c_str(),
- TimePointToString(filter_till).c_str(),
- limit,
- offset);
+ auto retQuery = db->query(
+ "SELECT * FROM events WHERE ( date('%q') >= date_from AND date_from > date('%q', 'start of day') ) OR "
+ " ( date('%q') >= date_till AND date_till > date('%q', 'start of day') ) OR "
+ " ( date_till > date('%q') AND date('%q', 'start of day') > date_from ) ORDER BY datetime(date_from) LIMIT %u "
+ "OFFSET %u;",
+ TimePointToString(filterFrom).c_str(),
+ TimePointToString(filterTill).c_str(),
+ TimePointToString(filterFrom).c_str(),
+ TimePointToString(filterTill).c_str(),
+ TimePointToString(filterFrom).c_str(),
+ TimePointToString(filterTill).c_str(),
+ limit,
+ offset);
+
+ if (retQuery == nullptr || retQuery->getRowCount() == 0) {
+ return std::vector<EventsTableRow>();
+ }
+
+ std::vector<EventsTableRow> ret;
+
+ do {
+ ret.push_back(EventsTableRow{
+ (*retQuery)[0].getUInt32(), // ID
+ (*retQuery)[1].getString(), // UID
+ (*retQuery)[2].getString(), // title
+ TimePointFromString((*retQuery)[3].getString().c_str()), // date_from
+ TimePointFromString((*retQuery)[4].getString().c_str()), // date_till
+ (*retQuery)[5].getUInt32(), // reminder
+ (*retQuery)[6].getUInt32(), // repeat
+ TimePointFromString((*retQuery)[7].getString().c_str()), // reminder_fired
+ (*retQuery)[8].getString(), // provider type
+ (*retQuery)[9].getString(), // provider id
+ (*retQuery)[10].getString() // provider iCalUid
+ });
+
+ } while (retQuery->nextRow());
+
+ return ret;
+}
+
+std::vector<EventsTableRow> EventsTable::selectByDate(TimePoint dateFilter, uint32_t offset, uint32_t limit)
+{
+ auto dateFilterFrom = dateFilter + date::days{1};
+ auto retQuery = db->query(
+ "SELECT * FROM events WHERE date_from < date('%q', 'start of day') AND date('%q', 'start of day') <= date_till "
+ "ORDER BY datetime(date_from) LIMIT %u OFFSET %u;",
+ TimePointToString(dateFilterFrom).c_str(),
+ TimePointToString(dateFilter).c_str(),
+ limit,
+ offset);
if (retQuery == nullptr || retQuery->getRowCount() == 0) {
return std::vector<EventsTableRow>();
@@ 714,7 758,6 @@ std::vector<EventsTableRow> EventsTable::getLimitOffset(uint32_t offset, uint32_
std::vector<EventsTableRow> EventsTable::getLimitOffsetByDate(uint32_t offset, uint32_t limit)
{
-
auto retQuery = db->query("SELECT * from events ORDER BY datetime(date_from) LIMIT %u OFFSET %u;", limit, offset);
if (retQuery == nullptr || retQuery->getRowCount() == 0) {
@@ 770,10 813,10 @@ uint32_t EventsTable::count()
return (*queryRet)[0].getUInt32();
}
-uint32_t EventsTable::countFromFilter(calendar::TimePoint from, calendar::TimePoint till)
+uint32_t EventsTable::countFromFilter(TimePoint from, TimePoint till)
{
auto queryRet = db->query(
- "SELECT COUNT(*) FROM events WHERE date_from >= date('%q') AND date_from < date('%q', 'start of day');",
+ "SELECT COUNT(*) FROM events WHERE date('%q') <= date_from AND date_from < date('%q', 'start of day');",
TimePointToString(from).c_str(),
TimePointToString(till).c_str());
@@ 784,6 827,21 @@ uint32_t EventsTable::countFromFilter(calendar::TimePoint from, calendar::TimePo
return (*queryRet)[0].getUInt32();
}
+uint32_t EventsTable::countFromDayFilter(TimePoint filter)
+{
+ auto filterFrom = filter + date::days{1};
+ auto queryRet = db->query("SELECT COUNT(*) FROM events WHERE date_from < datetime('%q', 'start of day') AND "
+ "datetime('%q', 'start of day') <= date_till;",
+ TimePointToString(filterFrom).c_str(),
+ TimePointToString(filter).c_str());
+
+ if (queryRet == nullptr || queryRet->getRowCount() == 0) {
+ return 0;
+ }
+
+ return (*queryRet)[0].getUInt32();
+}
+
uint32_t EventsTable::countByFieldId(const char *field, uint32_t id)
{
assert(0 && "Not implemented");
@@ 791,8 849,7 @@ uint32_t EventsTable::countByFieldId(const char *field, uint32_t id)
return 0;
}
-std::vector<EventsTableRow> EventsTable::SelectFirstUpcoming(calendar::TimePoint filter_from,
- calendar::TimePoint filter_till)
+std::vector<EventsTableRow> EventsTable::SelectFirstUpcoming(TimePoint filter_from, TimePoint filter_till)
{
auto retQuery = db->query("SELECT DATETIME(date_from, '-' || reminder || ' minutes') AS calc_dt, * "
"FROM events "
M module-db/Tables/EventsTable.hpp => module-db/Tables/EventsTable.hpp +11 -7
@@ 14,11 14,11 @@ struct EventsTableRow : public Record
{
std::string UID;
std::string title;
- calendar::TimePoint date_from = TIME_POINT_INVALID;
- calendar::TimePoint date_till = TIME_POINT_INVALID;
+ TimePoint date_from = TIME_POINT_INVALID;
+ TimePoint date_till = TIME_POINT_INVALID;
uint32_t reminder = 0;
uint32_t repeat = 0;
- calendar::TimePoint reminder_fired = TIME_POINT_INVALID;
+ TimePoint reminder_fired = TIME_POINT_INVALID;
std::string provider_type;
std::string provider_id;
std::string provider_iCalUid;
@@ 53,12 53,16 @@ class EventsTable : public Table<EventsTableRow, EventsTableFields>
bool drop();
EventsTableRow getByUID(const std::string &UID);
EventsTableRow getById(uint32_t id) override final;
- std::vector<EventsTableRow> selectByDatePeriod(calendar::TimePoint filter_from,
- calendar::TimePoint filter_till,
+ std::vector<EventsTableRow> selectByDatePeriod(TimePoint filter_from,
+ TimePoint filter_till,
uint32_t offset,
uint32_t limit);
+
+ std::vector<EventsTableRow> selectByDate(TimePoint date, uint32_t offset, uint32_t limit);
+
uint32_t count() override final;
- uint32_t countFromFilter(calendar::TimePoint from, calendar::TimePoint till);
+ uint32_t countFromFilter(TimePoint from, TimePoint till);
+ uint32_t countFromDayFilter(TimePoint filter);
uint32_t countByFieldId(const char *field, uint32_t id) override final;
std::vector<EventsTableRow> getLimitOffset(uint32_t offset, uint32_t limit) override final;
std::vector<EventsTableRow> getLimitOffsetByField(uint32_t offset,
@@ 67,7 71,7 @@ class EventsTable : public Table<EventsTableRow, EventsTableFields>
const char *str) override final;
std::vector<EventsTableRow> getLimitOffsetByDate(uint32_t offset, uint32_t limit);
- std::vector<EventsTableRow> SelectFirstUpcoming(calendar::TimePoint filter_from, calendar::TimePoint filter_till);
+ std::vector<EventsTableRow> SelectFirstUpcoming(TimePoint filter_from, TimePoint filter_till);
private:
const char *createTableQuery = "CREATE TABLE IF NOT EXISTS events("
M module-db/queries/calendar/QueryEventsGetFiltered.cpp => module-db/queries/calendar/QueryEventsGetFiltered.cpp +1 -4
@@ 5,10 5,7 @@
namespace db::query::events
{
- GetFiltered::GetFiltered(calendar::TimePoint filter_from,
- calendar::TimePoint filter_till,
- uint32_t offset,
- uint32_t limit)
+ GetFiltered::GetFiltered(TimePoint filter_from, TimePoint filter_till, uint32_t offset, uint32_t limit)
: Query(Query::Type::Read), filter_from(filter_from), filter_till(filter_till), offset(offset), limit(limit)
{}
M module-db/queries/calendar/QueryEventsGetFiltered.hpp => module-db/queries/calendar/QueryEventsGetFiltered.hpp +3 -6
@@ 13,14 13,11 @@ namespace db::query::events
class GetFiltered : public Query
{
public:
- GetFiltered(calendar::TimePoint filter_from,
- calendar::TimePoint filter_till,
- uint32_t offset = 0,
- uint32_t limit = UINT32_MAX);
+ GetFiltered(TimePoint filter_from, TimePoint filter_till, uint32_t offset = 0, uint32_t limit = UINT32_MAX);
[[nodiscard]] auto debugInfo() const -> std::string override;
- calendar::TimePoint filter_from;
- calendar::TimePoint filter_till;
+ TimePoint filter_from;
+ TimePoint filter_till;
uint32_t offset;
uint32_t limit;
};
A module-db/queries/calendar/QueryEventsGetFilteredByDay.cpp => module-db/queries/calendar/QueryEventsGetFilteredByDay.cpp +35 -0
@@ 0,0 1,35 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "QueryEventsGetFilteredByDay.hpp"
+
+namespace db::query::events
+{
+ GetFilteredByDay::GetFilteredByDay(TimePoint filterDate, uint32_t offset, uint32_t limit)
+ : Query(Query::Type::Read), filterDate(filterDate), offset(offset), limit(limit)
+ {}
+
+ auto GetFilteredByDay::debugInfo() const -> std::string
+ {
+ return "GetFilteredByDay";
+ }
+
+ GetFilteredByDayResult::GetFilteredByDayResult(const std::vector<EventsRecord> &records, uint32_t count)
+ : records{std::move(records)}, recordsCount{count}
+ {}
+
+ auto GetFilteredByDayResult::getResult() -> std::vector<EventsRecord>
+ {
+ return records;
+ }
+
+ auto GetFilteredByDayResult::getCountResult() -> uint32_t
+ {
+ return recordsCount;
+ }
+
+ auto GetFilteredByDayResult::debugInfo() const -> std::string
+ {
+ return "GetFilteredByDayResult";
+ }
+} // namespace db::query::events
A module-db/queries/calendar/QueryEventsGetFilteredByDay.hpp => module-db/queries/calendar/QueryEventsGetFilteredByDay.hpp +37 -0
@@ 0,0 1,37 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include "module-db/Interface/EventsRecord.hpp"
+#include <Common/Query.hpp>
+#include <string>
+#include <module-apps/application-calendar/data/dateCommon.hpp>
+
+namespace db::query::events
+{
+ class GetFilteredByDay : public Query
+ {
+ public:
+ GetFilteredByDay(TimePoint filterDate, uint32_t offset = 0, uint32_t limit = UINT32_MAX);
+ [[nodiscard]] auto debugInfo() const -> std::string override;
+
+ TimePoint filterDate;
+ uint32_t offset;
+ uint32_t limit;
+ };
+
+ class GetFilteredByDayResult : public QueryResult
+ {
+ std::vector<EventsRecord> records;
+ uint32_t recordsCount;
+
+ public:
+ GetFilteredByDayResult(const std::vector<EventsRecord> &records, uint32_t count);
+ auto getCountResult() -> uint32_t;
+ [[nodiscard]] auto getResult() -> std::vector<EventsRecord>;
+
+ [[nodiscard]] auto debugInfo() const -> std::string override;
+ };
+
+} // namespace db::query::events
M module-db/queries/calendar/QueryEventsSelectFirstUpcoming.cpp => module-db/queries/calendar/QueryEventsSelectFirstUpcoming.cpp +1 -1
@@ 5,7 5,7 @@
namespace db::query::events
{
- SelectFirstUpcoming::SelectFirstUpcoming(calendar::TimePoint filter_from, calendar::TimePoint filter_till)
+ SelectFirstUpcoming::SelectFirstUpcoming(TimePoint filter_from, TimePoint filter_till)
: Query(Query::Type::Read), filter_from(filter_from), filter_till(filter_till)
{}
M module-db/queries/calendar/QueryEventsSelectFirstUpcoming.hpp => module-db/queries/calendar/QueryEventsSelectFirstUpcoming.hpp +3 -3
@@ 14,11 14,11 @@ namespace db::query::events
class SelectFirstUpcoming : public Query
{
public:
- SelectFirstUpcoming(calendar::TimePoint filter_from, calendar::TimePoint filter_till);
+ SelectFirstUpcoming(TimePoint filter_from, TimePoint filter_till);
[[nodiscard]] auto debugInfo() const -> std::string override;
- calendar::TimePoint filter_from;
- calendar::TimePoint filter_till;
+ TimePoint filter_from;
+ TimePoint filter_till;
};
/// Result of SelectFirstUpcoming query
M module-db/tests/AlarmsRecord_tests.cpp => module-db/tests/AlarmsRecord_tests.cpp +1 -1
@@ 183,7 183,7 @@ TEST_CASE("Alarms Record tests")
}
auto getQuery = [&](uint32_t id,
- calendar::TimePoint alarmTime,
+ TimePoint alarmTime,
uint32_t snooze,
AlarmStatus status,
uint32_t repeat,
M module-db/tests/AlarmsTable_tests.cpp => module-db/tests/AlarmsTable_tests.cpp +5 -5
@@ 138,11 138,11 @@ TEST_CASE("Alarms Table tests")
REQUIRE(alarmsTbl.add(
AlarmsTableRow(5, TimePointFromString("2020-12-11 07:15:00"), 1, AlarmStatus::On, 1, "file2.mp3")));
- const std::array<calendar::TimePoint, 5> paramTime{TimePointFromString("2020-12-11 07:15:00"),
- TimePointFromString("2020-11-11 15:10:00"),
- TimePointFromString("2020-11-11 15:15:00"),
- TimePointFromString("2020-11-12 17:10:00"),
- TimePointFromString("2020-11-11 19:25:00")};
+ const std::array<TimePoint, 5> paramTime{TimePointFromString("2020-12-11 07:15:00"),
+ TimePointFromString("2020-11-11 15:10:00"),
+ TimePointFromString("2020-11-11 15:15:00"),
+ TimePointFromString("2020-11-12 17:10:00"),
+ TimePointFromString("2020-11-11 19:25:00")};
REQUIRE(alarmsTbl.count() == 5);
auto entries = alarmsTbl.getLimitOffset(0, 5);
M module-db/tests/EventsRecord_tests.cpp => module-db/tests/EventsRecord_tests.cpp +3 -6
@@ 730,7 730,7 @@ TEST_CASE("Events Record tests")
SECTION("Select first upcoming event")
{
- calendar::TimePoint start_date = TimePointFromString("2019-10-19 14:24:00");
+ TimePoint start_date = TimePointFromString("2019-10-19 14:24:00");
auto nextUpcoming = eventsRecordInterface.SelectFirstUpcoming(start_date, start_date);
REQUIRE(nextUpcoming.size() == 1);
EventsRecord nextEventsRecord = nextUpcoming.at(0);
@@ 799,9 799,7 @@ TEST_CASE("Events Record tests")
getAll(expectedRecords, numberOfEvents);
}
- auto getFiltered = [&](calendar::TimePoint filter_from,
- calendar::TimePoint filter_till,
- std::vector<EventsRecord> expected_records) {
+ auto getFiltered = [&](TimePoint filter_from, TimePoint filter_till, std::vector<EventsRecord> expected_records) {
auto query = std::make_shared<db::query::events::GetFiltered>(filter_from, filter_till);
auto ret = eventsRecordInterface.runQuery(query);
auto result = dynamic_cast<db::query::events::GetFilteredResult *>(ret.get());
@@ 1013,8 1011,7 @@ TEST_CASE("Events Record tests")
EditQueryICS(testRecord6.UID, testRecord6);
}
- [[maybe_unused]] auto selectFirstUpcomingEvent = [&](calendar::TimePoint filter_from,
- calendar::TimePoint filter_till) {
+ [[maybe_unused]] auto selectFirstUpcomingEvent = [&](TimePoint filter_from, TimePoint filter_till) {
auto query = std::make_shared<db::query::events::SelectFirstUpcoming>(filter_from, filter_till);
auto ret = eventsRecordInterface.runQuery(query);
auto result = dynamic_cast<db::query::events::SelectFirstUpcomingResult *>(ret.get());
M module-gui/gui/widgets/ListView.cpp => module-gui/gui/widgets/ListView.cpp +5 -0
@@ 141,6 141,11 @@ namespace gui
}
}
+ void ListView::setFocusOnElement(unsigned int elementNumber)
+ {
+ body->setFocusOnElement(elementNumber);
+ }
+
void ListView::setProvider(std::shared_ptr<ListItemProvider> prov)
{
if (prov != nullptr) {
M module-gui/gui/widgets/ListView.hpp => module-gui/gui/widgets/ListView.hpp +1 -0
@@ 87,6 87,7 @@ namespace gui
std::shared_ptr<ListItemProvider> getProvider();
void setOrientation(style::listview::Orientation value);
void setBoundaries(style::listview::Boundaries value);
+ void setFocusOnElement(unsigned int elementNumber);
void setScrollTopMargin(int value);
void setAlignment(const Alignment &value) override;
void onProviderDataUpdate();
M module-services/service-appmgr/data/MmiActionsParams.cpp => module-services/service-appmgr/data/MmiActionsParams.cpp +11 -1
@@ 38,7 38,7 @@ auto MMICallForwardingResult::getData() const -> std::tuple<std::string, std::st
void MMICallForwardingResult::accept(Visitor &v, std::string &displayMessage)
{
v.visit(*this, displayMessage);
-};
+}
MMIParams::MMIParams(std::string mmiData) : mmiData{std::move(mmiData)}
{}
@@ 62,3 62,13 @@ auto MMIResultParams::getCustomData() const noexcept -> std::shared_ptr<MMICusto
{
return customResult;
}
+
+void MMICallBarringResult::addMessages(const std::pair<MMIResultMessage, MMIResultMessage> &message) noexcept
+{
+ data.push_back(message);
+}
+
+auto MMICallBarringResult::getMessages(void) noexcept -> std::vector<std::pair<MMIResultMessage, MMIResultMessage>>
+{
+ return data;
+}
M module-services/service-appmgr/model/ApplicationManager.cpp => module-services/service-appmgr/model/ApplicationManager.cpp +3 -0
@@ 246,6 246,9 @@ namespace app::manager
handleAction(actionMsg);
return std::make_shared<sys::ResponseMessage>();
});
+ connect(typeid(GetCurrentDisplayLanguageRequest), [&](sys::Message *request) {
+ return std::make_shared<GetCurrentDisplayLanguageResponse>(displayLanguage);
+ });
auto convertibleToActionHandler = [this](sys::Message *request) { return handleMessageAsAction(request); };
connect(typeid(CellularSimRequestPinMessage), convertibleToActionHandler);
M module-services/service-appmgr/service-appmgr/Actions.hpp => module-services/service-appmgr/service-appmgr/Actions.hpp +1 -0
@@ 27,6 27,7 @@ namespace app::manager
CloseSystem,
Call,
Dial,
+ EmergencyDial,
ShowCallLog,
CreateSms,
ShowSmsTemplates,
M module-services/service-appmgr/service-appmgr/data/MmiActionsParams.hpp => module-services/service-appmgr/service-appmgr/data/MmiActionsParams.hpp +33 -2
@@ 30,7 30,9 @@ namespace app::manager::actions
NoneSpecified,
CallForwardingNotification,
CallForwardingData,
- Clir
+ Clir,
+ CallBarringNotification,
+ CallBarringData
};
enum class MMIResultMessage
@@ 38,7 40,18 @@ namespace app::manager::actions
NoneSpecifiedSuccess,
NoneSpecifiedFailed,
CommonFailure,
+ CommonMMINotSupported,
CommonNoMessage,
+ CommonVoice,
+ CommonData,
+ CommonFax,
+ CommonAsync,
+ CommonSync,
+ CommonAllDisabled,
+
+ CommonActivated,
+ CommonDeactivated,
+ CommonQuery,
ClirAccordingToSubscription,
ClirEnabled,
@@ 49,6 62,7 @@ namespace app::manager::actions
ClirTemporaryRestricted,
ClirTemporaryAllowed,
+ // Call forwarding
RegistrationSuccessful,
RegistrationFailed,
ErasureSuccessful,
@@ 56,7 70,12 @@ namespace app::manager::actions
DisablingSuccessful,
DisablingFailed,
EnablingSuccessful,
- EnablingFailed
+ EnablingFailed,
+ CallForwardingDisabled,
+
+ CallBarringActivated,
+ CallBarringDeactivated,
+
};
virtual auto getMessage() const -> std::vector<MMIResultMessage> = 0;
@@ 115,6 134,18 @@ namespace app::manager::actions
{}
};
+ class MMICallBarringResult : public MMICustomResultParams
+ {
+ public:
+ explicit MMICallBarringResult(MMIType type) : MMICustomResultParams(type)
+ {}
+ void addMessages(const std::pair<MMIResultMessage, MMIResultMessage> &message) noexcept;
+ auto getMessages(void) noexcept -> std::vector<std::pair<MMIResultMessage, MMIResultMessage>>;
+
+ private:
+ std::vector<std::pair<MMIResultMessage, MMIResultMessage>> data;
+ };
+
class MMIParams : public ActionParams
{
public:
A module-services/service-appmgr/service-appmgr/messages/GetCurrentDisplayLanguageRequest.hpp => module-services/service-appmgr/service-appmgr/messages/GetCurrentDisplayLanguageRequest.hpp +12 -0
@@ 0,0 1,12 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include "Message.hpp"
+
+namespace app::manager
+{
+ class GetCurrentDisplayLanguageRequest : public sys::Message
+ {};
+} // namespace app::manager
A module-services/service-appmgr/service-appmgr/messages/GetCurrentDisplayLanguageResponse.hpp => module-services/service-appmgr/service-appmgr/messages/GetCurrentDisplayLanguageResponse.hpp +24 -0
@@ 0,0 1,24 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <Service/Message.hpp>
+#include <i18n/i18n.hpp>
+
+namespace app::manager
+{
+ class GetCurrentDisplayLanguageResponse : public sys::ResponseMessage
+ {
+ public:
+ explicit GetCurrentDisplayLanguageResponse(Language language) : language(std::move(language))
+ {}
+ [[nodiscard]] auto getLanguage() const -> Language
+ {
+ return language;
+ }
+
+ private:
+ Language language;
+ };
+} // namespace app::manager
M module-services/service-appmgr/service-appmgr/messages/Message.hpp => module-services/service-appmgr/service-appmgr/messages/Message.hpp +2 -0
@@ 16,3 16,5 @@
#include "PowerSaveModeInitRequest.hpp"
#include "PreventBlockingRequest.hpp"
#include "ShutdownRequest.hpp"
+#include "GetCurrentDisplayLanguageRequest.hpp"
+#include "GetCurrentDisplayLanguageResponse.hpp"
M module-services/service-cellular/CellularRequestHandler.cpp => module-services/service-cellular/CellularRequestHandler.cpp +125 -9
@@ 15,6 15,9 @@
#include "service-cellular/requests/PinChangeRequest.hpp"
#include "service-cellular/requests/ImeiRequest.hpp"
#include "service-cellular/requests/UssdRequest.hpp"
+#include "service-cellular/service-cellular/requests/ClirRequest.hpp"
+#include "service-cellular/requests/CallForwardingRequest.hpp"
+#include "service-cellular/requests/CallBarringRequest.hpp"
#include <service-appmgr/model/ApplicationManager.hpp>
#include "service-cellular/service-cellular/requests/ClirRequest.hpp"
@@ 22,9 25,7 @@
#include <module-cellular/at/response.hpp>
-using namespace cellular;
-
-void CellularRequestHandler::handle(ImeiRequest &request, at::Result &result)
+void CellularRequestHandler::handle(cellular::ImeiRequest &request, at::Result &result)
{
if (!request.checkModemResponse(result)) {
request.setHandled(false);
@@ 36,7 37,7 @@ void CellularRequestHandler::handle(ImeiRequest &request, at::Result &result)
sys::Bus::SendUnicast(msg, app::manager::ApplicationManager::ServiceName, &cellular);
}
-void CellularRequestHandler::handle(UssdRequest &request, at::Result &result)
+void CellularRequestHandler::handle(cellular::UssdRequest &request, at::Result &result)
{
auto requestHandled = request.checkModemResponse(result);
@@ 50,7 51,7 @@ void CellularRequestHandler::handle(UssdRequest &request, at::Result &result)
request.setHandled(requestHandled);
}
-void CellularRequestHandler::handle(CallRequest &request, at::Result &result)
+void CellularRequestHandler::handle(cellular::CallRequest &request, at::Result &result)
{
if (!request.checkModemResponse(result)) {
request.setHandled(false);
@@ 66,28 67,28 @@ void CellularRequestHandler::handle(CallRequest &request, at::Result &result)
request.setHandled(true);
}
-void CellularRequestHandler::handle(SupplementaryServicesRequest &request, at::Result &result)
+void CellularRequestHandler::handle(cellular::SupplementaryServicesRequest &request, at::Result &result)
{
auto requestHandled = request.checkModemResponse(result);
request.setHandled(requestHandled);
sendMmiResult(requestHandled);
}
-void CellularRequestHandler::handle(PasswordRegistrationRequest &request, at::Result &result)
+void CellularRequestHandler::handle(cellular::PasswordRegistrationRequest &request, at::Result &result)
{
auto requestHandled = request.checkModemResponse(result);
request.setHandled(requestHandled);
sendMmiResult(requestHandled);
}
-void CellularRequestHandler::handle(PinChangeRequest &request, at::Result &result)
+void CellularRequestHandler::handle(cellular::PinChangeRequest &request, at::Result &result)
{
auto requestHandled = request.checkModemResponse(result);
request.setHandled(requestHandled);
sendMmiResult(requestHandled);
}
-void CellularRequestHandler::handle(ClirRequest &request, at::Result &result)
+void CellularRequestHandler::handle(cellular::ClirRequest &request, at::Result &result)
{
using namespace app::manager::actions;
using namespace cellular;
@@ 118,6 119,121 @@ void CellularRequestHandler::handle(ClirRequest &request, at::Result &result)
sys::Bus::SendUnicast(msg, app::manager::ApplicationManager::ServiceName, &cellular);
request.setHandled(requestHandled);
}
+
+void CellularRequestHandler::handle(cellular::CallForwardingRequest &request, at::Result &result)
+{
+ using namespace app::manager::actions;
+ using namespace cellular;
+ using namespace at::response;
+
+ auto requestHandled = request.checkModemResponse(result);
+ std::shared_ptr<MMICustomResultParams> response;
+ if (requestHandled) {
+ auto procedureType = request.getProcedureType();
+ if (procedureType == SupplementaryServicesRequest::ProcedureType::Registration) {
+ response =
+ std::make_shared<MMICallForwardingResult>(IMMICustomResultParams::MMIType::CallForwardingNotification);
+ response->addMessage(IMMICustomResultParams::MMIResultMessage::RegistrationSuccessful);
+ }
+ else if (procedureType == SupplementaryServicesRequest::ProcedureType::Deactivation) {
+ response =
+ std::make_shared<MMICallForwardingResult>(IMMICustomResultParams::MMIType::CallForwardingNotification);
+ response->addMessage(IMMICustomResultParams::MMIResultMessage::DisablingSuccessful);
+ }
+ else if (procedureType == SupplementaryServicesRequest::ProcedureType::Erasure) {
+ response =
+ std::make_shared<MMICallForwardingResult>(IMMICustomResultParams::MMIType::CallForwardingNotification);
+ response->addMessage(IMMICustomResultParams::MMIResultMessage::ErasureSuccessful);
+ }
+ else if (procedureType == SupplementaryServicesRequest::ProcedureType::Interrogation) {
+ std::vector<ccfc::ParsedCcfc> parsed;
+ if (at::response::ccfc::parse(result.response, parsed)) {
+ if (ccfc::isAnyActive(parsed)) {
+ auto numbers = ccfc::getNumbers(parsed);
+ response =
+ std::make_shared<MMICallForwardingResult>(IMMICustomResultParams::MMIType::CallForwardingData,
+ numbers.voice,
+ numbers.fax,
+ numbers.sync,
+ numbers.async);
+ }
+ else {
+ response = std::make_shared<MMICallForwardingResult>(
+ IMMICustomResultParams::MMIType::CallForwardingNotification);
+ response->addMessage(IMMICustomResultParams::MMIResultMessage::CallForwardingDisabled);
+ }
+ }
+ }
+ }
+
+ else {
+ if (result.code == at::Result::Code::ERROR &&
+ std::get<at::EquipmentErrorCode>(result.errorCode) == at::EquipmentErrorCode::PhoneBusy) {
+ response =
+ std::make_shared<MMICallForwardingResult>(IMMICustomResultParams::MMIType::CallForwardingNotification);
+ response->addMessage(IMMICustomResultParams::MMIResultMessage::CommonMMINotSupported);
+ }
+ }
+
+ if (response.get() == nullptr) {
+ response =
+ std::make_shared<MMICallForwardingResult>(IMMICustomResultParams::MMIType::CallForwardingNotification);
+ response->addMessage(IMMICustomResultParams::MMIResultMessage::CommonFailure);
+ }
+ auto msg = std::make_shared<CellularMMIResultMessage>(MMIResultParams::MMIResult::Success, response);
+ sys::Bus::SendUnicast(msg, app::manager::ApplicationManager::ServiceName, &cellular);
+ request.setHandled(requestHandled);
+}
+
+void CellularRequestHandler::handle(cellular::CallBarringRequest &request, at::Result &result)
+{
+ using namespace app::manager::actions;
+ using namespace at::response;
+ using namespace cellular;
+ auto requestHandled = request.checkModemResponse(result);
+
+ std::shared_ptr<MMICustomResultParams> response;
+ if (requestHandled) {
+ auto procedureType = request.getProcedureType();
+
+ if (procedureType == cellular::SupplementaryServicesRequest::ProcedureType::Activation) {
+ response = std::make_shared<MMICallBarringResult>(IMMICustomResultParams::MMIType::CallBarringNotification);
+ response->addMessage(IMMICustomResultParams::MMIResultMessage::CallBarringActivated);
+ }
+ else if (procedureType == SupplementaryServicesRequest::ProcedureType::Deactivation) {
+ response = std::make_shared<MMICallBarringResult>(IMMICustomResultParams::MMIType::CallBarringNotification);
+ response->addMessage(IMMICustomResultParams::MMIResultMessage::CallBarringDeactivated);
+ }
+ else if (procedureType == SupplementaryServicesRequest::ProcedureType::Interrogation) {
+ std::vector<clck::ClckParsed> parsed;
+
+ if (clck::parseQueryResponse(result.response, parsed)) {
+ MMICallBarringResult resp = MMICallBarringResult(IMMICustomResultParams::MMIType::CallBarringData);
+ std::sort(parsed.begin(), parsed.end(), clck::iterLessIter);
+ for (auto el : parsed) {
+ resp.addMessages(std::make_pair<IMMICustomResultParams::MMIResultMessage,
+ IMMICustomResultParams::MMIResultMessage>(
+ mmi::getClass(el.serviceClass), clck::getStatus(el.status)));
+ }
+ response = std::make_shared<MMICallBarringResult>(resp);
+ }
+ }
+ else {
+ response = std::make_shared<MMICallBarringResult>(IMMICustomResultParams::MMIType::CallBarringNotification);
+ response->addMessage(IMMICustomResultParams::MMIResultMessage::CommonMMINotSupported);
+ }
+ }
+
+ if (response == nullptr) {
+ response = std::make_shared<MMICallBarringResult>(IMMICustomResultParams::MMIType::CallBarringNotification);
+ response->addMessage(IMMICustomResultParams::MMIResultMessage::CommonFailure);
+ }
+
+ auto msg = std::make_shared<CellularMMIResultMessage>(MMIResultParams::MMIResult::Success, response);
+ sys::Bus::SendUnicast(msg, app::manager::ApplicationManager::ServiceName, &cellular);
+ request.setHandled(requestHandled);
+}
+
void CellularRequestHandler::sendMmiResult(bool result)
{
using namespace app::manager::actions;
M module-services/service-cellular/ServiceCellular.cpp => module-services/service-cellular/ServiceCellular.cpp +6 -4
@@ 211,7 211,7 @@ ServiceCellular::ServiceCellular() : sys::Service(serviceName, "", cellularStack
ServiceCellular::~ServiceCellular()
{
LOG_INFO("[ServiceCellular] Cleaning resources");
- settings->unregisterValueChange(settings::Cellular::volte_on);
+ settings->unregisterValueChange(settings::Cellular::volte_on, ::settings::SettingsScope::Global);
}
// this static function will be replaced by Settings API
@@ 233,8 233,10 @@ sys::ReturnCodes ServiceCellular::InitHandler()
board = EventManagerServiceAPI::GetBoard(this);
state.set(this, State::ST::WaitForStartPermission);
- settings->registerValueChange(settings::Cellular::volte_on,
- [this](const std::string &value) { volteChanged(value); });
+ settings->registerValueChange(
+ settings::Cellular::volte_on,
+ [this](const std::string &value) { volteChanged(value); },
+ ::settings::SettingsScope::Global);
return sys::ReturnCodes::Success;
}
@@ 335,7 337,7 @@ void ServiceCellular::registerMessageHandlers()
connect(typeid(CellularChangeVoLTEDataMessage), [&](sys::Message *request) -> sys::MessagePointer {
auto msg = static_cast<CellularChangeVoLTEDataMessage *>(request);
volteOn = msg->getVoLTEon();
- settings->setValue(settings::Cellular::volte_on, std::to_string(volteOn));
+ settings->setValue(settings::Cellular::volte_on, std::to_string(volteOn), settings::SettingsScope::Global);
return std::make_shared<CellularResponseMessage>(true);
});
M module-services/service-cellular/service-cellular/CellularRequestHandler.hpp => module-services/service-cellular/service-cellular/CellularRequestHandler.hpp +2 -0
@@ 19,6 19,8 @@ class CellularRequestHandler : public cellular::RequestHandler
void handle(cellular::SupplementaryServicesRequest &request, at::Result &result) final;
void handle(cellular::PinChangeRequest &request, at::Result &result) final;
void handle(cellular::ClirRequest &request, at::Result &result) final;
+ void handle(cellular::CallForwardingRequest &request, at::Result &result) final;
+ void handle(cellular::CallBarringRequest &request, at::Result &result) final;
private:
ServiceCellular &cellular;
M module-services/service-cellular/service-cellular/RequestHandler.hpp => module-services/service-cellular/service-cellular/RequestHandler.hpp +4 -0
@@ 15,6 15,8 @@ namespace cellular
class PinChangeRequest;
class ClipRequest;
class ClirRequest;
+ class CallForwardingRequest;
+ class CallBarringRequest;
class RequestHandler
{
@@ 26,5 28,7 @@ namespace cellular
virtual void handle(PinChangeRequest &request, at::Result &result) = 0;
virtual void handle(SupplementaryServicesRequest &request, at::Result &result) = 0;
virtual void handle(ClirRequest &request, at::Result &result) = 0;
+ virtual void handle(CallForwardingRequest &request, at::Result &result) = 0;
+ virtual void handle(CallBarringRequest &request, at::Result &result) = 0;
};
} // namespace cellular
M module-services/service-db/DBServiceAPI.cpp => module-services/service-db/DBServiceAPI.cpp +3 -3
@@ 137,9 137,9 @@ auto DBServiceAPI::MatchContactByPhoneNumber(sys::Service *serv, const utils::Ph
{
auto msg = std::make_shared<DBContactNumberMessage>(numberView);
- auto ret = sys::Bus::SendUnicast(msg, service::name::db, serv, DefaultTimeoutInMs);
+ auto ret = sys::Bus::SendUnicast(std::move(msg), service::name::db, serv, DefaultTimeoutInMs);
auto contactResponse = dynamic_cast<DBContactNumberResponseMessage *>(ret.second.get());
- if (contactResponse == nullptr) {
+ if (contactResponse == nullptr || contactResponse->retCode != sys::ReturnCodes::Success) {
LOG_ERROR("DB response error, return code: %s", c_str(ret.first));
return nullptr;
}
@@ 241,7 241,7 @@ auto DBServiceAPI::ContactSearch(sys::Service *serv, UTF8 primaryName, UTF8 alte
(alternativeName.length() > 0) ? alternativeName.c_str() : "",
(number.length() > 0) ? number.c_str() : "");
- auto ret = sys::Bus::SendUnicast(msg, service::name::db, serv, DefaultTimeoutInMs);
+ auto ret = sys::Bus::SendUnicast(std::move(msg), service::name::db, serv, DefaultTimeoutInMs);
auto contactResponse = dynamic_cast<DBContactResponseMessage *>(ret.second.get());
if (contactResponse == nullptr) {
LOG_ERROR("DB response error, return code: %s", c_str(ret.first));
M module-services/service-db/ServiceDB.cpp => module-services/service-db/ServiceDB.cpp +1 -1
@@ 334,7 334,7 @@ sys::MessagePointer ServiceDB::DataReceivedHandler(sys::DataMessage *msgl, sys::
if (ret.has_value()) {
responseMsg = std::make_shared<DBContactNumberResponseMessage>(
- sys::ReturnCodes::Success, std::make_unique<ContactRecord>(ret->contact));
+ sys::ReturnCodes::Success, std::make_unique<ContactRecord>(std::move(ret->contact)));
}
else {
responseMsg = std::make_shared<DBContactNumberResponseMessage>(sys::ReturnCodes::Failure,
M module-services/service-eink/CMakeLists.txt => module-services/service-eink/CMakeLists.txt +1 -1
@@ 16,7 16,7 @@ set(SOURCES
ServiceEink.cpp
EinkDisplay.cpp
messages/ImageMessage.cpp
- messages/PrepareDisplayRequest.cpp
+ messages/PrepareDisplayEarlyRequest.cpp
)
add_library(${PROJECT_NAME} STATIC ${SOURCES})
M module-services/service-eink/EinkDisplay.cpp => module-services/service-eink/EinkDisplay.cpp +102 -47
@@ 17,17 17,23 @@ namespace service::eink
constexpr auto LutsFileName = "Luts.bin";
constexpr auto LUTDSize = 16385;
constexpr auto LUTCSize = 64;
- constexpr auto LUTRSize = 256; ///< Needed due to \ref EINK_LUTS_FILE_PATH structure
+ constexpr auto LUTRSize = 256; ///< Needed due to \ref LutsFileName structure
constexpr auto LUTSTotalSize = LUTDSize + LUTCSize + LUTRSize;
- constexpr auto LUTVersionInterval = 3;
- constexpr auto LUTSubcritical = 12;
- constexpr auto LUTCritical = 13;
- EinkWaveFormSettings_t createDefaultWaveFormSettings(EinkWaveforms_e waveformMode)
+ constexpr auto LUTTemperatureMinimal = 0;
+ constexpr auto LUTTemperatureSubcritical = 38;
+ constexpr auto LUTTemperatureCritical = 43;
+
+ constexpr auto LUTTemperatureOffsetInterval = 3;
+ constexpr auto LUTTemperatureOffsetSubcritical = 12;
+ constexpr auto LUTTemperatureOffsetCritical = 13;
+
+ EinkWaveformSettings_t createDefaultWaveFormSettings(EinkWaveforms_e waveformMode)
{
- EinkWaveFormSettings_t settings{};
+ EinkWaveformSettings_t settings{};
settings.mode = waveformMode;
settings.temperature = DefaultSurroundingTemperature;
+ settings.useCounter = 0;
settings.LUTCData = nullptr;
settings.LUTCSize = 0;
settings.LUTDData = nullptr;
@@ 37,14 43,14 @@ namespace service::eink
} // namespace
EinkDisplay::EinkDisplay(::gui::Size screenSize)
- : size{screenSize}, waveformSettings{createDefaultWaveFormSettings(EinkWaveformGC16)},
+ : size{screenSize}, currentWaveform{createDefaultWaveFormSettings(EinkWaveformGC16)},
displayMode{EinkDisplayColorMode_e::EinkDisplayColorModeStandard}
{}
EinkDisplay::~EinkDisplay() noexcept
{
- delete[] waveformSettings.LUTCData;
- delete[] waveformSettings.LUTDData;
+ delete[] currentWaveform.LUTCData;
+ delete[] currentWaveform.LUTDData;
}
EinkStatus_e EinkDisplay::resetAndInit()
@@ 85,27 91,68 @@ namespace service::eink
EinkBpp_e EinkDisplay::getCurrentBitsPerPixelFormat() const noexcept
{
- if ((waveformSettings.mode == EinkWaveformA2) || (waveformSettings.mode == EinkWaveformDU2)) {
- return Eink4Bpp; /// this should be 1Bpp, but the OS is not ready for this
+ if ((currentWaveform.mode == EinkWaveformA2) || (currentWaveform.mode == EinkWaveformDU2)) {
+ return Eink4Bpp; // this should be 1Bpp, but the OS is not ready for this (in 1Bpp → halftones disappear)
}
return Eink4Bpp;
}
EinkStatus_e EinkDisplay::refresh(EinkDisplayTimingsMode_e refreshMode)
{
+ currentWaveform.useCounter += 1;
return EinkRefreshImage(pointTopLeft.x, pointTopLeft.y, size.width, size.height, refreshMode);
}
- bool EinkDisplay::changeWaveform(EinkWaveforms_e mode, std::int32_t temperature)
+ bool EinkDisplay::isNewWaveformNeeded(EinkWaveforms_e newMode, std::int32_t newTemperature) const
+ {
+ constexpr auto lenientTemperatureUseCounter = 50; // arbitrary. not documented
+ auto alloweLenientTemperature = currentWaveform.useCounter < lenientTemperatureUseCounter;
+
+ // at least: modes cannot differ
+ if (alloweLenientTemperature && newMode == currentWaveform.mode) {
+ bool temperatureFine = false;
+
+ switch (currentWaveform.mode) {
+ case EinkWaveformA2:
+ [[fallthrough]];
+ case EinkWaveformDU2:
+ temperatureFine = abs(newTemperature - currentWaveform.temperature) <= 3;
+ break;
+ case EinkWaveformINIT:
+ [[fallthrough]];
+ case EinkWaveformGLD16:
+ [[fallthrough]];
+ case EinkWaveformGC16:
+ temperatureFine = abs(newTemperature - currentWaveform.temperature) <= 2;
+ break;
+ }
+
+ if (temperatureFine) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ bool EinkDisplay::setWaveform(EinkWaveforms_e mode, std::int32_t temperature)
{
- if (temperature == waveformSettings.temperature && mode == waveformSettings.mode) {
- return EinkOK;
+ if (!isNewWaveformNeeded(mode, temperature)) {
+ return true;
}
- waveformSettings.temperature = temperature;
- waveformSettings.mode = mode;
- const auto segment = calculateWaveFormSegment(temperature);
- auto offset = calculateWaveFormOffset(mode, segment);
+ auto currentOffset =
+ toWaveformOffset(currentWaveform.mode, toWaveformTemperatureOffset(currentWaveform.temperature));
+ // assume it is changed
+ currentWaveform.useCounter = 0;
+ currentWaveform.temperature = temperature;
+ currentWaveform.mode = mode;
+
+ auto offset = toWaveformOffset(mode, toWaveformTemperatureOffset(temperature));
+
+ if (offset == currentOffset) {
+ // current waveform is still the best fit
+ return true;
+ }
auto file = std::fopen(LutsFileName, "rb");
if (file == nullptr) {
@@ 114,62 161,70 @@ namespace service::eink
}
auto fileHandlerCleanup = gsl::finally([&file]() { std::fclose(file); });
- resetWaveFormSettings();
+ resetWaveformSettings();
std::fseek(file, offset, SEEK_SET);
- std::fread(&waveformSettings.LUTDData[1], 1, LUTDSize, file);
+ std::fread(¤tWaveform.LUTDData[1], 1, LUTDSize, file);
// 0x00 - 1 frame, ... , 0x0F - 16 frames
- const uint8_t frameCount = waveformSettings.LUTDData[1] + 1;
+ const uint8_t waveformFrameCount = currentWaveform.LUTDData[1] + 1;
// (frameCount * 64) - size of actual LUT; (+1) - the byte containing frameCount; (+1) - EinkLUTD command
- waveformSettings.LUTDSize = (frameCount * 64) + 1 + 1;
+ currentWaveform.LUTDSize = (waveformFrameCount * 64) + 1 + 1;
offset += LUTDSize;
std::fseek(file, offset, SEEK_SET);
- std::fread(&waveformSettings.LUTCData[1], 1, LUTCSize, file);
+ std::fread(¤tWaveform.LUTCData[1], 1, LUTCSize, file);
- EinkUpdateWaveform(&waveformSettings);
+ EinkUpdateWaveform(¤tWaveform);
return true;
}
- unsigned int EinkDisplay::calculateWaveFormSegment(std::int32_t temperature) const
+ unsigned int EinkDisplay::toWaveformTemperatureOffset(std::int32_t temperature) noexcept
{
- if (temperature < 38) {
- return temperature / LUTVersionInterval;
- }
- if (temperature < 43) {
- return LUTSubcritical;
+ if (temperature >= LUTTemperatureCritical)
+ return LUTTemperatureOffsetCritical;
+ if (temperature >= LUTTemperatureSubcritical)
+ return LUTTemperatureOffsetSubcritical;
+ if (temperature < LUTTemperatureMinimal) {
+ temperature = 0;
}
- return LUTCritical;
+ return temperature / LUTTemperatureOffsetInterval;
+ }
+
+ unsigned int EinkDisplay::toWaveformOffset(unsigned short LUTbank, unsigned int temperatureOffset) noexcept
+ {
+ constexpr auto singleLUTOffset = (LUTTemperatureOffsetCritical + 1);
+ return LUTSTotalSize * (singleLUTOffset * LUTbank + temperatureOffset);
}
- unsigned int EinkDisplay::calculateWaveFormOffset(EinkWaveforms_e mode, unsigned int segment) const
+ unsigned int EinkDisplay::toWaveformOffset(EinkWaveforms_e mode, unsigned int temperatureOffset)
{
switch (mode) {
case EinkWaveformINIT:
- return LUTSTotalSize * segment;
+ return toWaveformOffset(0, temperatureOffset);
case EinkWaveformA2:
- return LUTSTotalSize * (14 + segment);
+ return toWaveformOffset(1, temperatureOffset);
case EinkWaveformDU2:
- return LUTSTotalSize * (28 + segment);
+ return toWaveformOffset(2, temperatureOffset);
case EinkWaveformGLD16:
- return LUTSTotalSize * (42 + segment);
+ return toWaveformOffset(3, temperatureOffset);
case EinkWaveformGC16:
- return LUTSTotalSize * (56 + segment);
+ return toWaveformOffset(4, temperatureOffset);
+ default:
+ throw std::invalid_argument{"Invalid waveform mode."};
}
- throw std::invalid_argument{"Invalid waveform mode."};
}
- void EinkDisplay::resetWaveFormSettings()
+ void EinkDisplay::resetWaveformSettings()
{
- delete[] waveformSettings.LUTDData;
- waveformSettings.LUTDSize = 0;
- waveformSettings.LUTDData = new std::uint8_t[LUTDSize + 1];
- waveformSettings.LUTDData[0] = EinkLUTD;
+ delete[] currentWaveform.LUTDData;
+ currentWaveform.LUTDSize = 0;
+ currentWaveform.LUTDData = new std::uint8_t[LUTDSize + 1];
+ currentWaveform.LUTDData[0] = EinkLUTD;
- delete[] waveformSettings.LUTCData;
- waveformSettings.LUTCSize = LUTCSize;
- waveformSettings.LUTCData = new std::uint8_t[LUTCSize + 1];
- waveformSettings.LUTCData[0] = EinkLUTC;
+ delete[] currentWaveform.LUTCData;
+ currentWaveform.LUTCSize = LUTCSize;
+ currentWaveform.LUTCData = new std::uint8_t[LUTCSize + 1];
+ currentWaveform.LUTCData[0] = EinkLUTC;
}
void EinkDisplay::setMode(EinkDisplayColorMode_e mode) noexcept
M module-services/service-eink/EinkDisplay.hpp => module-services/service-eink/EinkDisplay.hpp +8 -6
@@ 32,20 32,22 @@ namespace service::eink
void powerOff();
void shutdown();
- bool changeWaveform(EinkWaveforms_e mode, std::int32_t temperature);
+ bool setWaveform(EinkWaveforms_e mode, std::int32_t temperature);
void setMode(EinkDisplayColorMode_e mode) noexcept;
::gui::Size getSize() const noexcept;
private:
- unsigned int calculateWaveFormSegment(std::int32_t temperature) const;
- unsigned int calculateWaveFormOffset(EinkWaveforms_e mode, unsigned int segment) const;
- void resetWaveFormSettings();
- EinkBpp_e getCurrentBitsPerPixelFormat() const noexcept;
+ static unsigned int toWaveformTemperatureOffset(std::int32_t temperature) noexcept;
+ static unsigned int toWaveformOffset(unsigned short LUTbank, unsigned int temperatureOffset) noexcept;
+ static unsigned int toWaveformOffset(EinkWaveforms_e mode, unsigned int temperatureOffset);
+ bool isNewWaveformNeeded(EinkWaveforms_e newMode, int32_t newTemperature) const;
+ void resetWaveformSettings();
+ EinkBpp_e getCurrentBitsPerPixelFormat() const noexcept;
static constexpr ::gui::Point pointTopLeft{0, 0};
const ::gui::Size size;
- EinkWaveFormSettings_t waveformSettings;
+ EinkWaveformSettings_t currentWaveform;
EinkDisplayColorMode_e displayMode;
};
} // namespace service::eink
M module-services/service-eink/ServiceEink.cpp => module-services/service-eink/ServiceEink.cpp +11 -11
@@ 3,9 3,9 @@
#include "ServiceEink.hpp"
#include "messages/EinkModeMessage.hpp"
-#include "messages/PrepareDisplayRequest.hpp"
+#include "messages/PrepareDisplayEarlyRequest.hpp"
#include <service-gui/Common.hpp>
-#include <service-gui/messages/EinkReady.hpp>
+#include <service-gui/messages/EinkInitialized.hpp>
#include <time/ScopedTime.hpp>
#include <log/log.hpp>
@@ 32,8 32,8 @@ namespace service::eink
connect(typeid(ImageMessage),
[this](sys::Message *request) -> sys::MessagePointer { return handleImageMessage(request); });
- connect(typeid(PrepareDisplayRequest),
- [this](sys::Message *request) -> sys::MessagePointer { return handlePrepareRequest(request); });
+ connect(typeid(PrepareDisplayEarlyRequest),
+ [this](sys::Message *request) -> sys::MessagePointer { return handlePrepareEarlyRequest(request); });
}
sys::MessagePointer ServiceEink::DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *response)
@@ 51,7 51,7 @@ namespace service::eink
display.powerOn();
- auto msg = std::make_shared<service::gui::EinkReady>(display.getSize());
+ auto msg = std::make_shared<service::gui::EinkInitialized>(display.getSize());
sys::Bus::SendUnicast(msg, service::name::gui, this);
return sys::ReturnCodes::Success;
@@ 139,19 139,19 @@ namespace service::eink
{
display.powerOn();
- const auto isDeepRefresh = refreshMode == ::gui::RefreshModes::GUI_REFRESH_DEEP;
- if (const auto temperature = EinkGetTemperatureInternal(); isDeepRefresh) {
- display.changeWaveform(EinkWaveforms_e::EinkWaveformGC16, temperature);
+ const auto temperature = EinkGetTemperatureInternal();
+ if (refreshMode == ::gui::RefreshModes::GUI_REFRESH_DEEP) {
+ display.setWaveform(EinkWaveforms_e::EinkWaveformGC16, temperature);
display.dither();
}
else {
- display.changeWaveform(EinkWaveforms_e::EinkWaveformDU2, temperature);
+ display.setWaveform(EinkWaveforms_e::EinkWaveformDU2, temperature);
}
}
- sys::MessagePointer ServiceEink::handlePrepareRequest(sys::Message *message)
+ sys::MessagePointer ServiceEink::handlePrepareEarlyRequest(sys::Message *message)
{
- const auto waveformUpdateMsg = static_cast<service::eink::PrepareDisplayRequest *>(message);
+ const auto waveformUpdateMsg = static_cast<service::eink::PrepareDisplayEarlyRequest *>(message);
prepareDisplay(waveformUpdateMsg->getRefreshMode());
return sys::MessageNone{};
}
M module-services/service-eink/ServiceEink.hpp => module-services/service-eink/ServiceEink.hpp +1 -1
@@ 41,7 41,7 @@ namespace service::eink
sys::MessagePointer handleEinkModeChangedMessage(sys::Message *message);
sys::MessagePointer handleImageMessage(sys::Message *message);
- sys::MessagePointer handlePrepareRequest(sys::Message *message);
+ sys::MessagePointer handlePrepareEarlyRequest(sys::Message *message);
EinkDisplay display;
State currentState;
R module-services/service-eink/messages/PrepareDisplayRequest.cpp => module-services/service-eink/messages/PrepareDisplayEarlyRequest.cpp +3 -3
@@ 1,14 1,14 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
-#include "PrepareDisplayRequest.hpp"
+#include "PrepareDisplayEarlyRequest.hpp"
namespace service::eink
{
- PrepareDisplayRequest::PrepareDisplayRequest(::gui::RefreshModes refreshMode) : refreshMode{refreshMode}
+ PrepareDisplayEarlyRequest::PrepareDisplayEarlyRequest(::gui::RefreshModes refreshMode) : refreshMode{refreshMode}
{}
- auto PrepareDisplayRequest::getRefreshMode() const noexcept -> ::gui::RefreshModes
+ auto PrepareDisplayEarlyRequest::getRefreshMode() const noexcept -> ::gui::RefreshModes
{
return refreshMode;
}
R module-services/service-eink/messages/PrepareDisplayRequest.hpp => module-services/service-eink/messages/PrepareDisplayEarlyRequest.hpp +2 -2
@@ 9,10 9,10 @@
namespace service::eink
{
- class PrepareDisplayRequest : public EinkMessage
+ class PrepareDisplayEarlyRequest : public EinkMessage
{
public:
- explicit PrepareDisplayRequest(::gui::RefreshModes refreshMode);
+ explicit PrepareDisplayEarlyRequest(::gui::RefreshModes refreshMode);
[[nodiscard]] auto getRefreshMode() const noexcept -> ::gui::RefreshModes;
M module-services/service-gui/ServiceGUI.cpp => module-services/service-gui/ServiceGUI.cpp +16 -12
@@ 1,11 1,11 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "ServiceGUI.hpp"
#include "WorkerGUI.hpp"
#include "messages/DrawMessage.hpp"
-#include "messages/EinkReady.hpp"
+#include "messages/EinkInitialized.hpp"
#include <DrawCommand.hpp>
#include <FontManager.hpp>
@@ 14,7 14,7 @@
#include <service-eink/Common.hpp>
#include <service-eink/messages/ImageMessage.hpp>
#include <service-eink/messages/EinkMessage.hpp>
-#include <service-eink/messages/PrepareDisplayRequest.hpp>
+#include <service-eink/messages/PrepareDisplayEarlyRequest.hpp>
#include <SystemManager/SystemManager.hpp>
#include <gsl/gsl_util>
@@ 27,7 27,9 @@ namespace service::gui
constexpr auto ServiceGuiStackDepth = 4096U;
constexpr auto ContextsCount = 2;
constexpr auto CommandsQueueCapacity = 3;
- constexpr std::chrono::milliseconds ContextReleaseTimeout{1000};
+ constexpr std::chrono::milliseconds BSPEinkBusyTimeout{3000}; ///< sync with \ref BSP_EinkBusyTimeout
+ constexpr std::chrono::milliseconds RTOSMessageRoundtripTimeout{1000};
+ constexpr std::chrono::milliseconds ContextReleaseTimeout{BSPEinkBusyTimeout + RTOSMessageRoundtripTimeout};
} // namespace
ServiceGUI::ServiceGUI(const std::string &name, std::string parent)
@@ 52,8 54,8 @@ namespace service::gui
void ServiceGUI::registerMessageHandlers()
{
- connect(typeid(EinkReady),
- [this](sys::Message *request) -> sys::MessagePointer { return handleEinkReady(request); });
+ connect(typeid(EinkInitialized),
+ [this](sys::Message *request) -> sys::MessagePointer { return handleEinkInitialized(request); });
connect(typeid(DrawMessage),
[this](sys::Message *request) -> sys::MessagePointer { return handleDrawMessage(request); });
@@ 119,15 121,17 @@ namespace service::gui
setState(State::Suspended);
}
- prepareDisplay(drawMsg->mode);
+ if (!contextPool->isAnyContextLocked()) {
+ prepareDisplayEarly(drawMsg->mode);
+ }
notifyRenderer(std::move(drawMsg->commands), drawMsg->mode);
}
return sys::MessageNone{};
}
- void ServiceGUI::prepareDisplay(::gui::RefreshModes refreshMode)
+ void ServiceGUI::prepareDisplayEarly(::gui::RefreshModes refreshMode)
{
- auto msg = std::make_shared<service::eink::PrepareDisplayRequest>(refreshMode);
+ auto msg = std::make_shared<service::eink::PrepareDisplayEarlyRequest>(refreshMode);
sys::Bus::SendUnicast(msg, service::name::eink, this);
}
@@ 199,9 203,9 @@ namespace service::gui
cachedRender = std::nullopt;
}
- sys::MessagePointer ServiceGUI::handleEinkReady(sys::Message *message)
+ sys::MessagePointer ServiceGUI::handleEinkInitialized(sys::Message *message)
{
- const auto msg = static_cast<service::gui::EinkReady *>(message);
+ const auto msg = static_cast<service::gui::EinkInitialized *>(message);
contextPool = std::make_unique<ContextPool>(msg->getDisplaySize(), ContextsCount);
setState(State::Idle);
return sys::MessageNone{};
@@ 246,4 250,4 @@ namespace service::gui
{
return currentState == state;
}
-} /* namespace sgui */
+} // namespace service::gui
M module-services/service-gui/ServiceGUI.hpp => module-services/service-gui/ServiceGUI.hpp +2 -2
@@ 61,7 61,7 @@ namespace service::gui
void cacheRender(int contextId, ::gui::RefreshModes refreshMode);
void invalidateCache();
- void prepareDisplay(::gui::RefreshModes refreshMode);
+ void prepareDisplayEarly(::gui::RefreshModes refreshMode);
void notifyRenderer(std::list<std::unique_ptr<::gui::DrawCommand>> &&commands, ::gui::RefreshModes refreshMode);
void enqueueDrawCommands(DrawCommandsQueue::QueueItem &&item);
void sendOnDisplay(::gui::Context *context, int contextId, ::gui::RefreshModes refreshMode);
@@ 74,7 74,7 @@ namespace service::gui
sys::MessagePointer handleDrawMessage(sys::Message *message);
sys::MessagePointer handleGUIRenderingFinished(sys::Message *message);
- sys::MessagePointer handleEinkReady(sys::Message *message);
+ sys::MessagePointer handleEinkInitialized(sys::Message *message);
sys::MessagePointer handleImageDisplayedNotification(sys::Message *message);
std::unique_ptr<ContextPool> contextPool;
R module-services/service-gui/messages/EinkReady.hpp => module-services/service-gui/messages/EinkInitialized.hpp +2 -2
@@ 9,10 9,10 @@
namespace service::gui
{
- class EinkReady : public GUIMessage
+ class EinkInitialized : public GUIMessage
{
public:
- explicit EinkReady(::gui::Size displaySize) : einkDisplaySize{displaySize}
+ explicit EinkInitialized(::gui::Size displaySize) : einkDisplaySize{displaySize}
{}
[[nodiscard]] auto getDisplaySize() const noexcept -> ::gui::Size
M module-services/service-time/service-time/CalendarTimeEvents.hpp => module-services/service-time/service-time/CalendarTimeEvents.hpp +1 -1
@@ 27,7 27,7 @@ namespace stm
{
private:
EventsRecord eventRecord;
- calendar::TimePoint startTP = TIME_POINT_INVALID;
+ TimePoint startTP = TIME_POINT_INVALID;
protected:
const std::string timerName() override
M module-services/service-time/timeEvents/CalendarTimeEvents.cpp => module-services/service-time/timeEvents/CalendarTimeEvents.cpp +2 -2
@@ 37,8 37,8 @@ namespace stm
bool CalendarTimeEvents::sendNextEventQuery()
{
- calendar::TimePoint filterFrom = TimePointNow();
- calendar::TimePoint filterTill = filterFrom;
+ TimePoint filterFrom = TimePointNow();
+ TimePoint filterTill = filterFrom;
if (startTP != TIME_POINT_INVALID) {
filterFrom = std::min(startTP, filterFrom);
filterTill = filterFrom;
M module-utils/ical/ParserICS.cpp => module-utils/ical/ParserICS.cpp +5 -8
@@ 446,7 446,7 @@ auto Event::timeStringFrom(const std::string &icalTime) const -> std::string
getSecondsFromIcalTime(icalTime);
}
-auto Event::TimePointFromIcalDate(const std::string &icalDateTime) const -> calendar::TimePoint
+auto Event::TimePointFromIcalDate(const std::string &icalDateTime) const -> TimePoint
{
std::string icalDate(getDateFromIcalFormat(icalDateTime));
std::string icalTime(getTimeFromIcalFormat(icalDateTime));
@@ 459,7 459,7 @@ auto Event::TimePointFromIcalDate(const std::string &icalDateTime) const -> cale
return TimePointFromString(dateTime.c_str());
}
-auto Event::TimePointToIcalDate(const calendar::TimePoint &tp) const -> std::string
+auto Event::TimePointToIcalDate(const TimePoint &tp) const -> std::string
{
constexpr uint32_t bufferLimit = 16;
auto time = TimePointToTimeT(tp);
@@ 541,10 541,7 @@ auto Event::validateUID(const std::string &UID) -> bool
return validateDT(DTimestamp);
}
-Event::Event(const std::string &summary,
- const calendar::TimePoint from,
- calendar::TimePoint till,
- const std::string &uid)
+Event::Event(const std::string &summary, const TimePoint from, TimePoint till, const std::string &uid)
{
if (summary.empty()) {
isValid = false;
@@ 598,12 595,12 @@ auto Event::getSummary() const -> std::string
return summary;
}
-auto Event::getDTStartTimePoint() const -> calendar::TimePoint
+auto Event::getDTStartTimePoint() const -> TimePoint
{
return dtstart;
}
-auto Event::getDTEndTimePoint() const -> calendar::TimePoint
+auto Event::getDTEndTimePoint() const -> TimePoint
{
return dtend;
}
M module-utils/ical/ParserICS.hpp => module-utils/ical/ParserICS.hpp +7 -7
@@ 91,8 91,8 @@ class Event
{
std::string uid;
std::string summary;
- calendar::TimePoint dtstart;
- calendar::TimePoint dtend;
+ TimePoint dtstart;
+ TimePoint dtend;
auto isDate(const std::string &dt) -> bool;
auto isTime(const std::string &dt) -> bool;
@@ 112,13 112,13 @@ class Event
[[nodiscard]] auto dateStringFrom(const std::string &icalDate) const -> std::string;
[[nodiscard]] auto timeStringFrom(const std::string &icalTime) const -> std::string;
- [[nodiscard]] auto TimePointFromIcalDate(const std::string &icalDateTime) const -> calendar::TimePoint;
- [[nodiscard]] auto TimePointToIcalDate(const calendar::TimePoint &tp) const -> std::string;
+ [[nodiscard]] auto TimePointFromIcalDate(const std::string &icalDateTime) const -> TimePoint;
+ [[nodiscard]] auto TimePointToIcalDate(const TimePoint &tp) const -> std::string;
public:
bool isValid = true;
Event() = default;
- Event(const std::string &summary, calendar::TimePoint from, calendar::TimePoint till, const std::string &uid);
+ Event(const std::string &summary, TimePoint from, TimePoint till, const std::string &uid);
void setUID(const std::string &property);
void setSummary(const std::string &property);
@@ 127,8 127,8 @@ class Event
[[nodiscard]] auto getUID() const -> std::string;
[[nodiscard]] auto getSummary() const -> std::string;
- [[nodiscard]] auto getDTStartTimePoint() const -> calendar::TimePoint;
- [[nodiscard]] auto getDTEndTimePoint() const -> calendar::TimePoint;
+ [[nodiscard]] auto getDTStartTimePoint() const -> TimePoint;
+ [[nodiscard]] auto getDTEndTimePoint() const -> TimePoint;
[[nodiscard]] auto getDTStartString() const -> std::string;
[[nodiscard]] auto getDTEndString() const -> std::string;
M module-utils/time/TimeRangeParser.cpp => module-utils/time/TimeRangeParser.cpp +2 -2
@@ 19,8 19,8 @@ namespace utils::time
return utils::localize.get(utils::time::Locale::getPM());
}
- std::string TimeRangeParser::getCalendarTimeString(calendar::TimePoint startDate,
- calendar::TimePoint endDate,
+ std::string TimeRangeParser::getCalendarTimeString(TimePoint startDate,
+ TimePoint endDate,
Version version,
bool isMode24H)
{
M module-utils/time/TimeRangeParser.hpp => module-utils/time/TimeRangeParser.hpp +2 -2
@@ 20,8 20,8 @@ namespace utils::time
std::string AMPMtoString(bool isAm);
public:
- std::string getCalendarTimeString(calendar::TimePoint startDate,
- calendar::TimePoint endDate,
+ std::string getCalendarTimeString(TimePoint startDate,
+ TimePoint endDate,
Version version = Version::normal,
bool isMode24H = false);
};
M module-utils/time/time_conversion.hpp => module-utils/time/time_conversion.hpp +5 -0
@@ 226,6 226,11 @@ namespace utils
return minutes;
}
+ time_t getHours() const
+ {
+ return hours;
+ }
+
UTF8 str(DisplayedFormat displayedFormat = DisplayedFormat::Auto0M) const;
// uses default format
M test/pytest/service-desktop/test_calendar.py => test/pytest/service-desktop/test_calendar.py +1 -0
@@ 4,6 4,7 @@ import pytest
from harness.interface.defs import status
import copy
+@pytest.mark.skip("not working on CI")
@pytest.mark.service_desktop_test
def test_calendar(harness):
# add events
M tools/download_asset.py => tools/download_asset.py +43 -12
@@ 15,6 15,7 @@ import os
import requests
import sys
from tqdm import tqdm
+import time
class Getter(object):
@@ 24,12 25,6 @@ class Getter(object):
self.host = 'https://api.github.com/repos'
self.organisation = 'mudita'
self.repo = 'ecoboot'
- self.restPrefix = self.host
- self.restPrefix += '/'
- self.restPrefix += self.organisation
- self.restPrefix += '/'
- self.restPrefix += self.repo
- self.restPrefix += '/'
self.apitoken = None
self.ghLogin = None
self.getGitRoot()
@@ 38,6 33,16 @@ class Getter(object):
self.releases = []
self.workdir = ""
+ def genRestPrefix(self):
+ self.restPrefix = self.host
+ self.restPrefix += '/'
+ self.restPrefix += self.organisation
+ self.restPrefix += '/'
+ self.restPrefix += self.repo
+ self.restPrefix += '/'
+ return self.restPrefix
+
+
def getGitRoot(self):
'Find git root directory'
self.gitRepo = git.Repo(os.getcwd(), search_parent_directories=True)
@@ 78,7 83,8 @@ class Getter(object):
self.args = args
self.getGHLogin(args)
self.getApiToken(args)
- request = self.restPrefix + "releases"
+ request = self.genRestPrefix() + "releases"
+ print ("Request:", request)
headers = {'accept': 'application/vnd.github.v3+json'}
page = 0
itemsOnPage = 100
@@ 89,12 95,21 @@ class Getter(object):
response = requests.get(request, auth=(self.ghLogin, self.apitoken), headers=headers, params=queryParams)
if response.status_code != requests.codes.ok:
print("download error:", response.status_code)
- print(response.content)
+ print("content:", response.content)
sys.exit(1)
items = json.loads(response.content)
count = len(items)
self.releases += items
- self.releases.sort(key=lambda r: r['published_at'], reverse=True)
+ drafts = []
+ releases = []
+ for item in self.releases:
+ if item['published_at'] is None:
+ drafts.append(item)
+ else:
+ releases.append(item)
+ releases.sort(key=lambda r: r['published_at'], reverse=True)
+ self.releases=drafts
+ self.releases.extend(releases)
def listReleases(self, args):
self.getReleases(args)
@@ 106,7 121,8 @@ class Getter(object):
def downloadRelease(self, args):
print(sys._getframe().f_code.co_name)
self.getReleases(args)
- print(args.tag)
+ print("tag:", args.tag)
+ print("asset:", args.asset)
release = None
if args.tag is None:
release = self.releases[0]
@@ 119,7 135,19 @@ class Getter(object):
print("No release with tag:", args.tag)
print("release:", release['tag_name'])
assets = release['assets']
- self.downloadAsset(assets[0])
+ if len(assets) > 1 and args.asset is None:
+ print("Available assets")
+ i=0
+ for asset in assets:
+ print(i, asset['name'])
+ i+=1
+ print("Use `-a <number>` to select file")
+ return
+ if args.asset is not None:
+ self.downloadAsset(assets[int(args.asset)])
+ else:
+ self.downloadAsset(assets[0])
+
def downloadAsset(self, asset):
self.createWorkdir()
@@ 131,8 159,10 @@ class Getter(object):
auth=(self.ghLogin, self.apitoken),
headers=headers,
stream=True)
+ destination_file = self.args.workdir + "/" + asset['name']
+ print("downloading to:", destination_file)
progres_bar = tqdm(total=asset['size'], unit='iB', unit_scale=True)
- with open(self.args.workdir + "/" + asset['name'], 'wb') as fd:
+ with open(destination_file, 'wb') as fd:
for chunk in response.iter_content(chunk_size=1024):
progres_bar.update(len(chunk))
fd.write(chunk)
@@ 183,6 213,7 @@ def main():
description="Download Release based on tag or the latest")
getReleases_args.set_defaults(func=getter.downloadRelease)
getReleases_args.add_argument('tag', help="Download release with selected tag", nargs='?')
+ getReleases_args.add_argument('-a', '--asset', help="Asset name to download, use asset number")
args = parser.parse_args()
getter.repo = args.repository