diff --git a/frontend/device/kindle/device.lua b/frontend/device/kindle/device.lua index 676ef2fbf..487666756 100644 --- a/frontend/device/kindle/device.lua +++ b/frontend/device/kindle/device.lua @@ -66,9 +66,15 @@ function Kindle:supportsScreensaver() end end -function Kindle:setTime(hour, min) +function Kindle:setDateTime(year, month, day, hour, min, sec) if hour == nil or min == nil then return true end - if os.execute(string.format("date -s '%d:%d'", hour, min)) == 0 then + local command + if year and month and day then + command = string.format("date -s '%d-%d-%d %d:%d:%d'", year, month, day, hour, min, sec) + else + command = string.format("date -s '%d:%d'",hour, min) + end + if os.execute(command) == 0 then os.execute('hwclock -u -w') return true else diff --git a/frontend/device/kobo/device.lua b/frontend/device/kobo/device.lua index 45ca1ee15..db7b26cc2 100644 --- a/frontend/device/kobo/device.lua +++ b/frontend/device/kobo/device.lua @@ -184,9 +184,15 @@ function Kobo:init() end end -function Kobo:setTime(hour, min) +function Kobo:setDateTime(year, month, day, hour, min, sec) if hour == nil or min == nil then return true end - if os.execute(string.format("date -s '%d:%d'", hour, min)) == 0 then + local command + if year and month and day then + command = string.format("date -s '%d-%d-%d %d:%d:%d'", year, month, day, hour, min, sec) + else + command = string.format("date -s '%d:%d'",hour, min) + end + if os.execute(command) == 0 then os.execute('hwclock -u -w') return true else diff --git a/frontend/device/pocketbook/device.lua b/frontend/device/pocketbook/device.lua index 378f8acb2..c979951bc 100644 --- a/frontend/device/pocketbook/device.lua +++ b/frontend/device/pocketbook/device.lua @@ -77,9 +77,15 @@ function PocketBook:init() Generic.init(self) end -function PocketBook:setTime(hour, min) +function PocketBook:setDateTime(year, month, day, hour, min, sec) if hour == nil or min == nil then return true end - if os.execute(string.format("date -s '%d:%d'", hour, min)) == 0 then + local command + if year and month and day then + command = string.format("date -s '%d-%d-%d %d:%d:%d'", year, month, day, hour, min, sec) + else + command = string.format("date -s '%d:%d'",hour, min) + end + if os.execute(command) == 0 then os.execute('hwclock -u -w') return true else diff --git a/frontend/device/sdl/device.lua b/frontend/device/sdl/device.lua index b5ea316b0..e786f2cca 100644 --- a/frontend/device/sdl/device.lua +++ b/frontend/device/sdl/device.lua @@ -59,9 +59,15 @@ function Device:init() Generic.init(self) end -function Device:setTime(hour, min) +function Device:setDateTime(year, month, day, hour, min, sec) if hour == nil or min == nil then return true end - if os.execute(string.format("date -s '%d:%d'", hour, min)) == 0 then + local command + if year and month and day then + command = string.format("date -s '%d-%d-%d %d:%d:%d'", year, month, day, hour, min, sec) + else + command = string.format("date -s '%d:%d'",hour, min) + end + if os.execute(command) == 0 then os.execute('hwclock -u -w') return true else diff --git a/frontend/ui/elements/common_settings_menu_table.lua b/frontend/ui/elements/common_settings_menu_table.lua index eddea49f4..55ece1303 100644 --- a/frontend/ui/elements/common_settings_menu_table.lua +++ b/frontend/ui/elements/common_settings_menu_table.lua @@ -1,3 +1,4 @@ +local DateWidget = require("ui/widget/datewidget") local Device = require("device") local InfoMessage = require("ui/widget/infomessage") local Language = require("ui/language") @@ -20,34 +21,70 @@ if Device:hasFrontlight() then } end -if Device:setTime() then +if Device:setDateTime() then common_settings.time = { - text = _("Set time"), - callback = function() - local now_t = os.date("*t") - local curr_hour = now_t.hour - local curr_min = now_t.min - local time_widget = TimeWidget:new{ - hour = curr_hour, - min = curr_min, - ok_text = _("Set time"), - title_text = _("Set time"), - callback = function(time) - if Device:setTime(time.hour, time.min) then - now_t = os.date("*t") - UIManager:show(InfoMessage:new{ - text = T(_("Current time: %1:%2"), string.format("%02d", now_t.hour), - string.format("%02d", now_t.min)) - }) - else - UIManager:show(InfoMessage:new{ - text = _("Time couldn't be set"), - }) - end - end + text = _("Time and date"), + sub_item_table = { + { + text = _("Set time"), + callback = function() + local now_t = os.date("*t") + local curr_hour = now_t.hour + local curr_min = now_t.min + local time_widget = TimeWidget:new{ + hour = curr_hour, + min = curr_min, + ok_text = _("Set time"), + title_text = _("Set time"), + callback = function(time) + if Device:setDateTime(nil, nil, nil, time.hour, time.min) then + now_t = os.date("*t") + UIManager:show(InfoMessage:new{ + text = T(_("Current time: %1:%2"), string.format("%02d", now_t.hour), + string.format("%02d", now_t.min)) + }) + else + UIManager:show(InfoMessage:new{ + text = _("Time couldn't be set"), + }) + end + end + } + UIManager:show(time_widget) + end, + }, + { + text = _("Set date"), + callback = function() + local now_t = os.date("*t") + local curr_year = now_t.year + local curr_month = now_t.month + local curr_day = now_t.day + local date_widget = DateWidget:new{ + year = curr_year, + month = curr_month, + day = curr_day, + ok_text = _("Set date"), + title_text = _("Set date"), + callback = function(time) + now_t = os.date("*t") + if Device:setDateTime(time.year, time.month, time.day, now_t.hour, now_t.min, now_t.sec) then + now_t = os.date("*t") + UIManager:show(InfoMessage:new{ + text = T(_("Current date: %1-%2-%3"), now_t.year, string.format("%02d", now_t.month), + string.format("%02d", now_t.day)) + }) + else + UIManager:show(InfoMessage:new{ + text = _("Date couldn't be set"), + }) + end + end + } + UIManager:show(date_widget) + end, } - UIManager:show(time_widget) - end, + } } end diff --git a/frontend/ui/widget/datewidget.lua b/frontend/ui/widget/datewidget.lua new file mode 100644 index 000000000..91eff7634 --- /dev/null +++ b/frontend/ui/widget/datewidget.lua @@ -0,0 +1,231 @@ +local Blitbuffer = require("ffi/blitbuffer") +local ButtonTable = require("ui/widget/buttontable") +local CenterContainer = require("ui/widget/container/centercontainer") +local CloseButton = require("ui/widget/closebutton") +local Device = require("device") +local FrameContainer = require("ui/widget/container/framecontainer") +local Geom = require("ui/geometry") +local GestureRange = require("ui/gesturerange") +local Font = require("ui/font") +local HorizontalGroup = require("ui/widget/horizontalgroup") +local InputContainer = require("ui/widget/container/inputcontainer") +local LineWidget = require("ui/widget/linewidget") +local OverlapGroup = require("ui/widget/overlapgroup") +local NumberPickerWidget = require("ui/widget/numberpickerwidget") +local TextBoxWidget = require("ui/widget/textboxwidget") +local TextWidget = require("ui/widget/textwidget") +local UIManager = require("ui/uimanager") +local VerticalGroup = require("ui/widget/verticalgroup") +local WidgetContainer = require("ui/widget/container/widgetcontainer") +local _ = require("gettext") +local Screen = Device.screen + +local DateWidget = InputContainer:new{ + title_face = Font:getFace("x_smalltfont"), + width = nil, + height = nil, + day = 1, + month = 1, + year = 2017, + ok_text = _("OK"), + cancel_text = _("Cancel"), +} + +function DateWidget:init() + self.medium_font_face = Font:getFace("ffont") + self.light_bar = {} + self.screen_width = Screen:getSize().w + self.screen_height = Screen:getSize().h + self.width = self.screen_width * 0.95 + if Device:hasKeys() then + self.key_events = { + Close = { {"Back"}, doc = "close date" } + } + end + if Device:isTouchDevice() then + self.ges_events = { + TapCloseFL = { + GestureRange:new{ + ges = "tap", + range = Geom:new{ + w = self.screen_width, + h = self.screen_height, + } + }, + }, + } + end + self:update() +end + +function DateWidget:update() + local year_widget = NumberPickerWidget:new{ + show_parent = self, + width = self.screen_width * 0.2, + value = self.year, + value_min = 2017, + value_max = 2037, + value_step = 1, + value_hold_step = 4, + } + local month_widget = NumberPickerWidget:new{ + show_parent = self, + width = self.screen_width * 0.2, + value = self.month, + value_min = 1, + value_max = 12, + value_step = 1, + value_hold_step = 3, + } + local day_widget = NumberPickerWidget:new{ + show_parent = self, + width = self.screen_width * 0.2, + value = self.day, + value_min = 1, + value_max = 31, + value_step = 1, + value_hold_step = 5, + date_month = month_widget, + date_year = year_widget, + } + local dash_space = TextBoxWidget:new{ + text = "–", + alignment = "center", + face = self.title_face, + bold = true, + width = self.screen_width * 0.1, + } + local date_group = HorizontalGroup:new{ + align = "center", + year_widget, + dash_space, + month_widget, + dash_space, + day_widget, + } + + local date_title = FrameContainer:new{ + padding = Screen:scaleBySize(5), + margin = Screen:scaleBySize(2), + bordersize = 0, + TextWidget:new{ + text = self.title_text, + face = self.title_face, + bold = true, + width = self.screen_width * 0.95, + }, + } + local date_line = LineWidget:new{ + dimen = Geom:new{ + w = self.width, + h = Screen:scaleBySize(2), + } + } + local date_bar = OverlapGroup:new{ + dimen = { + w = self.width, + h = date_title:getSize().h + }, + date_title, + CloseButton:new{ window = self, }, + } + local buttons = { + { + { + text = self.cancel_text, + callback = function() + self:onClose() + end, + }, + { + text = self.ok_text, + callback = function() + if self.callback then + self.year = year_widget:getValue() + self.month = month_widget:getValue() + self.day = day_widget:getValue() + self:callback(self) + end + self:onClose() + end, + }, + } + } + + local ok_cancel_buttons = ButtonTable:new{ + width = Screen:getWidth()*0.9, + buttons = buttons, + show_parent = self, + } + + self.date_frame = FrameContainer:new{ + radius = 5, + bordersize = 3, + padding = 0, + margin = 0, + background = Blitbuffer.COLOR_WHITE, + VerticalGroup:new{ + align = "left", + date_bar, + date_line, + CenterContainer:new{ + dimen = Geom:new{ + w = self.screen_width * 0.95, + h = self.screen_height * 0.25, + }, + date_group + }, + date_line, + ok_cancel_buttons + } + } + self[1] = WidgetContainer:new{ + align = "center", + dimen =Geom:new{ + x = 0, y = 0, + w = self.screen_width, + h = self.screen_height, + }, + FrameContainer:new{ + bordersize = 0, + padding = Screen:scaleBySize(5), + self.date_frame, + } + } + UIManager:setDirty(self, function() + return "ui", self.date_frame.dimen + end) +end + +function DateWidget:onCloseWidget() + UIManager:setDirty(nil, function() + return "partial", self.date_frame.dimen + end) + return true +end + +function DateWidget:onShow() + UIManager:setDirty(self, function() + return "ui", self.date_frame.dimen + end) + return true +end + +function DateWidget:onAnyKeyPressed() + UIManager:close(self) + return true +end + +function DateWidget:onTapCloseFL(arg, ges_ev) + if ges_ev.pos:notIntersectWith(self.date_frame.dimen) then + self:onClose() + end + return true +end + +function DateWidget:onClose() + UIManager:close(self) + return true +end + +return DateWidget diff --git a/frontend/ui/widget/numberpickerwidget.lua b/frontend/ui/widget/numberpickerwidget.lua index f19567dcd..bdecb7bf3 100644 --- a/frontend/ui/widget/numberpickerwidget.lua +++ b/frontend/ui/widget/numberpickerwidget.lua @@ -24,6 +24,9 @@ local NumberPickerWidget = InputContainer:new{ value_step = 1, value_hold_step = 4, value_table = nil, + -- in case we need calculate number of days in a given month and year + date_month = nil, + date_year = nil, } function NumberPickerWidget:init() @@ -52,10 +55,16 @@ function NumberPickerWidget:paintWidget() width = self.width, show_parent = self.show_parent, callback = function() + if self.date_month and self.date_year then + self.value_max = self:getDaysInMonth(self.date_month:getValue(), self.date_year:getValue()) + end self.value = self:changeValue(self.value, self.value_step, self.value_max, self.value_min) self:update() end, hold_callback = function() + if self.date_month and self.date_year then + self.value_max = self:getDaysInMonth(self.date_month:getValue(), self.date_year:getValue()) + end self.value = self:changeValue(self.value, self.value_hold_step, self.value_max, self.value_min) self:update() end @@ -69,10 +78,16 @@ function NumberPickerWidget:paintWidget() width = self.width, show_parent = self.show_parent, callback = function() + if self.date_month and self.date_year then + self.value_max = self:getDaysInMonth(self.date_month:getValue(), self.date_year:getValue()) + end self.value = self:changeValue(self.value, self.value_step * -1, self.value_max, self.value_min) self:update() end, hold_callback = function() + if self.date_month and self.date_year then + self.value_max = self:getDaysInMonth(self.date_month:getValue(), self.date_year:getValue()) + end self.value = self:changeValue(self.value, self.value_hold_step * -1, self.value_max, self.value_min) self:update() end @@ -142,17 +157,34 @@ function NumberPickerWidget:changeValue(value, step, max, min) else value = value + step if value > max then - value = value - max + 1 + value = min elseif value < min then - value = max + 1 + value + value = max end end return value end +function NumberPickerWidget:getDaysInMonth(month, year) + local days_in_month = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } + local days = days_in_month[month] + -- check for leap year + if (month == 2) then + if year % 4 == 0 then + if year % 100 == 0 then + if year % 400 == 0 then + days = 29 + end + else + days = 29 + end + end + end + return days +end + function NumberPickerWidget:getValue() return self.value end return NumberPickerWidget - diff --git a/frontend/ui/widget/timewidget.lua b/frontend/ui/widget/timewidget.lua index e71e8809d..048f58b60 100644 --- a/frontend/ui/widget/timewidget.lua +++ b/frontend/ui/widget/timewidget.lua @@ -61,7 +61,6 @@ function TimeWidget:update() local hour_widget = NumberPickerWidget:new{ show_parent = self, width = self.screen_width * 0.2, - height = nil, value = self.hour, value_min = 0, value_max = 23, @@ -71,7 +70,6 @@ function TimeWidget:update() local min_widget = NumberPickerWidget:new{ show_parent = self, width = self.screen_width * 0.2, - height = nil, value = self.min, value_min = 0, value_max = 59,