Terminal plugin (#2646)

This commit is contained in:
Hzj_jie
2017-04-01 23:50:24 -07:00
committed by Qingping Hou
parent eb641b6abc
commit 339e16636b
8 changed files with 189 additions and 35 deletions

View File

@@ -37,6 +37,7 @@ local order = {
"storage_stat",
"cloud_storage",
"read_timer",
"terminal",
"----------------------------",
"advanced_settings",
"developer_options",

View File

@@ -55,6 +55,7 @@ local order = {
"synchronize_time",
"progress_sync",
"zsync",
"terminal",
},
search = {
"dictionary_lookup",

View File

@@ -1,30 +1,56 @@
local InputContainer = require("ui/widget/container/inputcontainer")
local Blitbuffer = require("ffi/blitbuffer")
local CenterContainer = require("ui/widget/container/centercontainer")
local Font = require("ui/font")
local Device = require("device")
local GestureRange = require("ui/gesturerange")
local Font = require("ui/font")
local FrameContainer = require("ui/widget/container/framecontainer")
local HorizontalGroup = require("ui/widget/horizontalgroup")
local ImageWidget = require("ui/widget/imagewidget")
local TextBoxWidget = require("ui/widget/textboxwidget")
local HorizontalSpan = require("ui/widget/horizontalspan")
local UIManager = require("ui/uimanager")
local Geom = require("ui/geometry")
local GestureRange = require("ui/gesturerange")
local HorizontalGroup = require("ui/widget/horizontalgroup")
local HorizontalSpan = require("ui/widget/horizontalspan")
local ImageWidget = require("ui/widget/imagewidget")
local InputContainer = require("ui/widget/container/inputcontainer")
local ScrollTextWidget = require("ui/widget/scrolltextwidget")
local TextBoxWidget = require("ui/widget/textboxwidget")
local UIManager = require("ui/uimanager")
local WidgetContainer = require("ui/widget/container/widgetcontainer")
local _ = require("gettext")
local Input = require("device").input
local Screen = require("device").screen
local _ = require("gettext")
local Blitbuffer = require("ffi/blitbuffer")
--[[
Widget that displays an informational message
it vanishes on key press or after a given timeout
Example:
local _ = require("gettext")
local UIManager = require("ui/uimanager")
local sample
sample = InfoMessage:new{
text = _("Some message"),
-- Usually the hight of a InfoMessage is self-adaptive. If this field is actively set, a
-- scrollbar may be shown. This variable is usually helpful to display a large chunk of text
-- which may exceed the height of the screen.
height = 400,
-- Set to false to hide the icon, and also the span between the icon and text.
show_icon = false,
timeout = 5, -- This widget will vanish in 5 seconds.
}
sample_input:onShowKeyboard()
UIManager:show(sample_input)
]]
local InfoMessage = InputContainer:new{
modal = true,
face = Font:getFace("infofont", 25),
text = "",
timeout = nil, -- in seconds
width = nil, -- The width of the InfoMessage. Keep it nil to use default value.
height = nil, -- The height of the InfoMessage. If this field is set, a scrollbar may be shown.
image = nil, -- The image shows at the left of the InfoMessage.
image_width = nil, -- The image width if image is used. Keep it nil to use original width.
image_height = nil, -- The image height if image is used. Keep it nil to use original height.
-- Whether the icon should be shown. If it is false, self.image will be ignored.
show_icon = true,
}
function InfoMessage:init()
@@ -46,16 +72,48 @@ function InfoMessage:init()
}
}
end
local image_widget
if self.image then
image_widget = ImageWidget:new{
image = self.image,
width = self.image_width,
height = self.image_height,
if self.show_icon then
if self.image then
image_widget = ImageWidget:new{
image = self.image,
width = self.image_width,
height = self.image_height,
}
else
image_widget = ImageWidget:new{
file = "resources/info-i.png",
}
end
else
image_widget = WidgetContainer:new()
end
local text_width
if self.width == nil then
text_width = Screen:getWidth() * 2 / 3
else
text_width = self.width - image_widget:getSize().w
if text_width < 0 then
text_width = 0
end
end
local text_widget
if self.height then
text_widget = ScrollTextWidget:new{
text = self.text,
face = self.face,
width = text_width,
height = self.height,
dialog = self,
}
else
image_widget = ImageWidget:new{
file = "resources/info-i.png",
text_widget = TextBoxWidget:new{
text = self.text,
face = self.face,
width = text_width,
}
end
-- we construct the actual content here because self.text is only available now
@@ -67,12 +125,8 @@ function InfoMessage:init()
HorizontalGroup:new{
align = "center",
image_widget,
HorizontalSpan:new{ width = 10 },
TextBoxWidget:new{
text = self.text,
face = self.face,
width = Screen:getWidth()*2/3,
}
HorizontalSpan:new{ width = (self.show_icon and 10 or 0) },
text_widget,
}
}
}

View File

@@ -108,6 +108,7 @@ function InputText:initTextBox(text, char_added)
fgcolor = fgcolor,
width = self.width,
height = self.height,
dialog = self.parent,
}
else
self.text_widget = TextBoxWidget:new{

View File

@@ -46,7 +46,7 @@ function ScrollTextWidget:init()
self.v_scroll_bar = VerticalScrollBar:new{
enable = visible_line_count < total_line_count,
low = 0,
high = visible_line_count/total_line_count,
high = visible_line_count / total_line_count,
width = self.scroll_bar_width,
height = self.height,
}

View File

@@ -13,14 +13,14 @@ Example:
]]
local Blitbuffer = require("ffi/blitbuffer")
local Widget = require("ui/widget/widget")
local Geom = require("ui/geometry")
local LineWidget = require("ui/widget/linewidget")
local RenderText = require("ui/rendertext")
local Screen = require("device").screen
local Geom = require("ui/geometry")
local util = require("util")
local logger = require("logger")
local TimeVal = require("ui/timeval")
local Widget = require("ui/widget/widget")
local logger = require("logger")
local util = require("util")
local TextBoxWidget = Widget:new{
text = nil,
@@ -225,7 +225,8 @@ function TextBoxWidget:_renderText(start_row_idx, end_row_idx)
if start_row_idx < 1 then start_row_idx = 1 end
if end_row_idx > #self.vertical_string_list then end_row_idx = #self.vertical_string_list end
local row_count = end_row_idx == 0 and 1 or end_row_idx - start_row_idx + 1
local h = self.line_height_px * row_count
local h = self.line_height_px * row_count
if self._bb then self._bb:free() end
self._bb = Blitbuffer.new(self.width, h)
self._bb:fill(Blitbuffer.COLOR_WHITE)
local y = font_height

View File

@@ -1,6 +1,6 @@
local Widget = require("ui/widget/widget")
local Geom = require("ui/geometry")
local Blitbuffer = require("ffi/blitbuffer")
local Geom = require("ui/geometry")
local Widget = require("ui/widget/widget")
local VerticalScrollBar = Widget:new{
enable = true,
@@ -29,10 +29,10 @@ end
function VerticalScrollBar:paintTo(bb, x, y)
if not self.enable then return end
bb:paintBorder(x, y, self.width, self.height,
self.bordersize, self.bordercolor, self.radius)
bb:paintRect(x + self.bordersize, y + self.bordersize + self.low*self.height,
self.width - 2*self.bordersize,
self.height * (self.high - self.low), self.rectcolor)
self.bordersize, self.bordercolor, self.radius)
bb:paintRect(x + self.bordersize, y + self.bordersize + self.low * self.height,
self.width - 2 * self.bordersize,
(self.height - 2 * self.bordersize) * (self.high - self.low), self.rectcolor)
end
return VerticalScrollBar

View File

@@ -0,0 +1,96 @@
local DataStorage = require("datastorage")
local Font = require("ui/font")
local InfoMessage = require("ui/widget/infomessage")
local InputDialog = require("ui/widget/inputdialog")
local UIManager = require("ui/uimanager")
local WidgetContainer = require("ui/widget/container/widgetcontainer")
local logger = require("logger")
local util = require("ffi/util")
local _ = require("gettext")
local Screen = require("device").screen
local Terminal = WidgetContainer:new{
name = "terminal",
dump_file = util.realpath(DataStorage:getDataDir()) .. "/terminal_output.txt",
}
function Terminal:init()
self.ui.menu:registerToMainMenu(self)
end
function Terminal:start()
self.input = InputDialog:new{
title = _("Enter a command and press \"Execute\""),
text_height = Screen:getHeight() * 0.4,
input_type = "string",
buttons = {{{
text = _("Cancel"),
callback = function()
UIManager:close(self.input)
end,
}, {
text = _("Execute"),
is_enter_default = true,
callback = function()
UIManager:close(self.input)
self:execute()
end,
}}},
}
self.input:onShowKeyboard()
UIManager:show(self.input)
end
function Terminal:execute()
local command = self.input:getInputText()
UIManager:show(InfoMessage:new{
text = _("Executing ..."),
timeout = 0.1,
})
UIManager:forceRePaint()
local std_out = io.popen(command)
local entries = { command }
if std_out then
while true do
local line = std_out:read()
if line == nil then break end
table.insert(entries, line)
end
std_out:close()
else
table.insert(entries, _("Failed to execute command."))
end
self:dump(entries)
table.insert(entries, _("Output will also be dumped to"))
table.insert(entries, self.dump_file)
UIManager:show(InfoMessage:new{
cface = Font:getFace("ffont", 18),
text = _("Command output\n") .. table.concat(entries, "\n"),
show_icon = false,
width = Screen:getWidth() * 0.8,
height = Screen:getHeight() * 0.8,
})
end
function Terminal:dump(entries)
local content = table.concat(entries, "\n")
local file = io.open(self.dump_file, "w")
if file then
file:write(content)
file:close()
else
logger.warn("Failed to dump terminal output " .. content .. " to " .. self.dump_file)
end
end
function Terminal:addToMainMenu(menu_items)
menu_items.terminal = {
text = _("Terminal emulator"),
callback = function()
self:start()
end,
}
end
return Terminal