diff --git a/linspector/frontends/urlish.py b/linspector/frontends/urlish.py
index 6fb54f3..ec20f56 100644
--- a/linspector/frontends/urlish.py
+++ b/linspector/frontends/urlish.py
@@ -21,36 +21,41 @@ You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
"""
+"""
+TODO:
+
+ General:
+
+ - think about if a simple scrollable list of jobs may be a lot easier to use
+ in combination with some tabs for job list, hostgroup jobs, host jobs etc.
+ i think this is a lot more flexible when reloading data. using the current
+ we have to rebuild the complete tree on reloading. or figure out how to
+ rebuild only selected nodes on reload. when using a tab/list based solution
+ we could even build a tab that on shows current errors, one for warnings etc.
+ these could we rebuild on access or on key stroke. these lists then only need
+ some action handlers for disabling/enabling or for showing detailed
+ information about the selected job. i think the tab/list approach is much
+ easier to handle then jumping like a monkey through a tree structure... ;)
+
+ For the tree based solution:
+
+ - remove all this global stuff and set needed stuff as arguments
+
+ - fix mouse handling; nice feature to select stuff using the mouse. currently
+ it raises an exception.
+"""
+
import urwid
from logging import getLogger
from linspector.frontends.frontend import Frontend
-__version__ = "0.1.1"
+__version__ = "0.1.2"
logger = getLogger(__name__)
-class JobWidget(urwid.FlowWidget):
- def __init__(self):
- pass
-
-
-class JobListBox(urwid.WidgetWrap):
- def __init__(self):
- self.body = urwid.SimpleListWalker([])
- self.listbox = urwid.ListBox(self.body)
- urwid.WidgetWrap.__init__(self, self.listbox)
-
- def keypress(self, size, key):
- if key == ':':
- main_frame.set_focus('footer')
- command_prompt.set_caption(':')
- else:
- return self.listbox.keypress(size, key)
-
-
class CommandPrompt(urwid.Edit):
def __init__(self):
urwid.Edit.__init__(self, '')
@@ -141,13 +146,91 @@ class CommandPrompt(urwid.Edit):
return urwid.Edit.keypress(self, size, key)
-def update(main_loop, user_data):
- thread_count = interface.get_thread_count()
- header_bar.set_text(" Linspector,"
- " Jobs: " + str(interface.get_job_count()) +
- " Threads: " + str(thread_count["Num Threads"]) +
- "/" + str(thread_count["Max Threads"]))
- main_loop.set_alarm_in(1, update)
+class ExampleTreeWidget(urwid.TreeWidget):
+ def __init__(self, node):
+ self.__super.__init__(node)
+ #self.expanded = False
+ #self.update_expanded_icon()
+
+ def get_display_text(self):
+ return self.get_node().get_value()['name']
+
+
+class ExampleNode(urwid.TreeNode):
+ def load_widget(self):
+ return ExampleTreeWidget(self)
+
+
+class ServiceParentNode(urwid.ParentNode):
+ def load_widget(self):
+ return ExampleTreeWidget(self)
+
+ def load_child_keys(self):
+ data = self.get_value()
+ return range(len(data['children']))
+
+ def load_child_node(self, key):
+ childdata = self.get_value()['children'][key]
+ childdepth = self.get_depth() + 1
+ if 'children' in childdata:
+ childclass = ServiceParentNode
+ else:
+ childclass = ExampleNode
+ return childclass(childdata, parent=self, key=key, depth=childdepth)
+
+
+class HostParentNode(urwid.ParentNode):
+ def load_widget(self):
+ return ExampleTreeWidget(self)
+
+ def load_child_keys(self):
+ data = self.get_value()
+ return range(len(data['children']))
+
+ def load_child_node(self, key):
+ childdata = self.get_value()['children'][key]
+ childdepth = self.get_depth() + 1
+ if 'children' in childdata:
+ childclass = ServiceParentNode
+ else:
+ childclass = ExampleNode
+ return childclass(childdata, parent=self, key=key, depth=childdepth)
+
+
+class HostgroupParentNode(urwid.ParentNode):
+ def load_widget(self):
+ return ExampleTreeWidget(self)
+
+ def load_child_keys(self):
+ data = self.get_value()
+ return range(len(data['children']))
+
+ def load_child_node(self, key):
+ childdata = self.get_value()['children'][key]
+ childdepth = self.get_depth() + 1
+ if 'children' in childdata:
+ childclass = HostParentNode
+ else:
+ childclass = ExampleNode
+ return childclass(childdata, parent=self, key=key, depth=childdepth)
+
+
+class RootParentNode(urwid.ParentNode):
+ def load_widget(self):
+ return ExampleTreeWidget(self)
+
+ def load_child_keys(self):
+ data = self.get_value()
+ return range(len(data['children']))
+
+ def load_child_node(self, key):
+ childdata = self.get_value()['children'][key]
+ childdepth = self.get_depth() + 1
+ if 'children' in childdata:
+ childclass = HostgroupParentNode
+ else:
+ childclass = ExampleNode
+ return childclass(childdata, parent=self, key=key, depth=childdepth)
class UrlishFrontend(Frontend):
@@ -162,26 +245,98 @@ class UrlishFrontend(Frontend):
global loop
global interface
- palette = [('top', 'white', 'dark red'),
+ palette = [('body', 'white', 'black'),
+ ('foot_bar', 'white', 'black'),
+ ('top', 'white', 'dark red'),
('status', 'white', 'dark blue'),
('prompt', 'white', 'black')]
+ foot_text = [('title', "Navigation:"), " ",
+ ('key', "UP"), ",", ('key', "DOWN"), ",",
+ ('key', "PAGE UP"), ",", ('key', "PAGE DOWN"),
+ " ",
+ ('key', "+"), ",",
+ ('key', "-"), " ",
+ ('key', "LEFT"), " ",
+ ('key', "HOME"), " ",
+ ('key', "END")]
+
interface = linspector_interface
+ top_node = RootParentNode(get_example_tree())
+ job_list_box = urwid.TreeListBox(urwid.TreeWalker(top_node))
+ job_list_box.offset_rows = 1
+
header_message = ' Linspector (' + str(linspector_interface.get_version()) + ')'
header_bar = urwid.Text(header_message, align='left')
header = urwid.Pile([urwid.AttrMap(header_bar, 'top')])
command_prompt = CommandPrompt()
+ foot_bar = urwid.Text(foot_text, align='left')
+
welcome_message = ' Type ":h " for help, ":q " to quit'
status_bar = urwid.Text(welcome_message, align='left')
- footer = urwid.Pile([urwid.AttrMap(status_bar, 'status'), urwid.AttrMap(command_prompt, 'prompt')])
-
- job_list_box = JobListBox()
+ footer = urwid.Pile([urwid.AttrMap(foot_bar, 'foot_bar'),
+ urwid.AttrMap(status_bar, 'status'),
+ urwid.AttrMap(command_prompt, 'prompt')])
main_frame = urwid.Frame(body=job_list_box, header=header, footer=footer)
- loop = urwid.MainLoop(main_frame, palette)
+ loop = urwid.MainLoop(main_frame, palette, unhandled_input=self.unhandled_input, handle_mouse=False)
loop.set_alarm_in(0, update)
- loop.run()
\ No newline at end of file
+ loop.run()
+
+ @staticmethod
+ def unhandled_input(key):
+ if key in (':'):
+ main_frame.set_focus('footer')
+ command_prompt.set_caption(':')
+ elif key in ('c'):
+ #collapse all children of current node
+ pass
+ elif key in ('C'):
+ #collapse all nodes
+ pass
+ elif key in ('d'):
+ #disable all jobs for current node
+ pass
+ elif key in ('e'):
+ #enable all jobs for current node
+ pass
+ elif key in ('r'):
+ #reload child data of current node
+ pass
+ elif key in ('R'):
+ #reload child data of all nodes
+ pass
+ elif key in ('x'):
+ #expand all children of current node
+ pass
+ elif key in ('X'):
+ #expand all nodes
+ pass
+
+
+def update(main_loop, user_data):
+ thread_count = interface.get_thread_count()
+ header_bar.set_text(" Linspector,"
+ " Jobs: " + str(interface.get_job_count()) +
+ " Threads: " + str(thread_count["Num Threads"]) +
+ "/" + str(thread_count["Max Threads"]))
+ main_loop.set_alarm_in(1, update)
+
+
+def get_example_tree():
+ retval = {"name": "ROOT", "children": []}
+ for i in range(10):
+ retval['children'].append({"name": "HOSTGROUP " + str(i)})
+ retval['children'][i]['children'] = []
+ for j in range(5):
+ retval['children'][i]['children'].append({"name": "HOST " + str(i) + "." + str(j)})
+ retval['children'][i]['children'][j]['children'] = []
+ for k in range(3):
+ retval['children'][i]['children'][j]['children'].append({"name": "SERVICE " + str(i) +
+ "." + str(j) +
+ "." + str(k)})
+ return retval
\ No newline at end of file