console: add a tabs widget, and use it for flowview.

This commit is contained in:
Aldo Cortesi 2015-03-29 17:40:43 +13:00
parent cfeee347d9
commit cacd09fafc
3 changed files with 87 additions and 79 deletions

View File

@ -27,7 +27,6 @@ class ConsoleState(flow.State):
self.focus = None self.focus = None
self.follow_focus = None self.follow_focus = None
self.default_body_view = contentview.get("Auto") self.default_body_view = contentview.get("Auto")
self.view_flow_mode = common.VIEW_FLOW_REQUEST
self.flowsettings = weakref.WeakKeyDictionary() self.flowsettings = weakref.WeakKeyDictionary()
self.last_search = None self.last_search = None
@ -458,7 +457,7 @@ class ConsoleMaster(flow.FlowMaster):
signals.push_view_state.send(self) signals.push_view_state.send(self)
self.loop.widget = window.Window( self.loop.widget = window.Window(
self, self,
flowdetailview.FlowDetailsView(low), flowdetailview.FlowDetailsView(flow),
None, None,
statusbar.StatusBar(self, flowdetailview.footer) statusbar.StatusBar(self, flowdetailview.footer)
) )
@ -493,13 +492,13 @@ class ConsoleMaster(flow.FlowMaster):
) )
self.loop.draw_screen() self.loop.draw_screen()
def view_flow(self, flow): def view_flow(self, flow, tab_offset=0):
signals.push_view_state.send(self) signals.push_view_state.send(self)
self.state.set_focus_flow(flow) self.state.set_focus_flow(flow)
self.help_context = flowview.help_context self.help_context = flowview.help_context
self.loop.widget = window.Window( self.loop.widget = window.Window(
self, self,
flowview.FlowView(self, self.state, flow), flowview.FlowView(self, self.state, flow, tab_offset),
flowview.FlowViewHeader(self, flow), flowview.FlowViewHeader(self, flow),
statusbar.StatusBar(self, flowview.footer) statusbar.StatusBar(self, flowview.footer)
) )

View File

@ -1,7 +1,7 @@
from __future__ import absolute_import from __future__ import absolute_import
import os, sys, copy import os, sys, copy
import urwid import urwid
from . import common, grideditor, contentview, signals, searchable from . import common, grideditor, contentview, signals, searchable, tabs
from .. import utils, flow, controller from .. import utils, flow, controller
from ..protocol.http import HTTPRequest, HTTPResponse, CONTENT_MISSING, decoded from ..protocol.http import HTTPRequest, HTTPResponse, CONTENT_MISSING, decoded
@ -109,25 +109,48 @@ class FlowViewHeader(urwid.WidgetWrap):
cache = utils.LRUCache(200) cache = utils.LRUCache(200)
TAB_REQ = 0
TAB_RESP = 1
class FlowView(urwid.WidgetWrap): class FlowView(tabs.Tabs):
highlight_color = "focusfield" highlight_color = "focusfield"
def __init__(self, master, state, flow): def __init__(self, master, state, flow, tab_offset):
self.master, self.state, self.flow = master, state, flow self.master, self.state, self.flow = master, state, flow
tabs.Tabs.__init__(self,
[
(self.tab_request, self.view_request),
(self.tab_response, self.view_response),
],
tab_offset
)
self.show()
self.last_displayed_body = None self.last_displayed_body = None
if self.state.view_flow_mode == common.VIEW_FLOW_RESPONSE:
self.view_response()
else:
self.view_request()
signals.flow_change.connect(self.sig_flow_change) signals.flow_change.connect(self.sig_flow_change)
def tab_request(self):
if self.flow.intercepted and not self.flow.reply.acked and not self.flow.response:
return "Request intercepted"
else:
return "Request"
def tab_response(self):
if self.flow.intercepted and not self.flow.reply.acked and self.flow.response:
return "Response intercepted"
else:
return "Response"
def view_request(self):
return self.conn_text(self.flow.request)
def view_response(self):
return self.conn_text(self.flow.response)
def sig_flow_change(self, sender, flow): def sig_flow_change(self, sender, flow):
if flow == self.flow: if flow == self.flow:
if self.state.view_flow_mode == common.VIEW_FLOW_RESPONSE and self.flow.response: self.show()
self.view_response()
else:
self.view_request()
def content_view(self, viewmode, conn): def content_view(self, viewmode, conn):
if conn.content == CONTENT_MISSING: if conn.content == CONTENT_MISSING:
@ -136,7 +159,7 @@ class FlowView(urwid.WidgetWrap):
else: else:
full = self.state.get_flow_setting( full = self.state.get_flow_setting(
self.flow, self.flow,
(self.state.view_flow_mode, "fullcontents"), (self.tab_offset, "fullcontents"),
False False
) )
if full: if full:
@ -157,7 +180,7 @@ class FlowView(urwid.WidgetWrap):
def viewmode_get(self): def viewmode_get(self):
override = self.state.get_flow_setting( override = self.state.get_flow_setting(
self.flow, self.flow,
(self.state.view_flow_mode, "prettyview") (self.tab_offset, "prettyview")
) )
return self.state.default_body_view if override is None else override return self.state.default_body_view if override is None else override
@ -203,50 +226,6 @@ class FlowView(urwid.WidgetWrap):
] ]
return searchable.Searchable(self.state, txt) return searchable.Searchable(self.state, txt)
def _tab(self, content, attr):
p = urwid.Text(content)
p = urwid.Padding(p, align="left", width=("relative", 100))
p = urwid.AttrWrap(p, attr)
return p
def wrap_body(self, active, body):
parts = []
if self.flow.intercepted and not self.flow.reply.acked and not self.flow.response:
qt = "Request intercepted"
else:
qt = "Request"
if active == common.VIEW_FLOW_REQUEST:
parts.append(self._tab(qt, "heading"))
else:
parts.append(self._tab(qt, "heading_inactive"))
if self.flow.intercepted and not self.flow.reply.acked and self.flow.response:
st = "Response intercepted"
else:
st = "Response"
if active == common.VIEW_FLOW_RESPONSE:
parts.append(self._tab(st, "heading"))
else:
parts.append(self._tab(st, "heading_inactive"))
h = urwid.Columns(parts)
f = urwid.Frame(
body,
header=h
)
return f
def view_request(self):
self.state.view_flow_mode = common.VIEW_FLOW_REQUEST
body = self.conn_text(self.flow.request)
self._w = self.wrap_body(common.VIEW_FLOW_REQUEST, body)
def view_response(self):
self.state.view_flow_mode = common.VIEW_FLOW_RESPONSE
body = self.conn_text(self.flow.response)
self._w = self.wrap_body(common.VIEW_FLOW_RESPONSE, body)
def set_method_raw(self, m): def set_method_raw(self, m):
if m: if m:
self.flow.request.method = m self.flow.request.method = m
@ -320,7 +299,7 @@ class FlowView(urwid.WidgetWrap):
self.edit_form(conn) self.edit_form(conn)
def edit(self, part): def edit(self, part):
if self.state.view_flow_mode == common.VIEW_FLOW_REQUEST: if self.tab_offset == TAB_REQ:
message = self.flow.request message = self.flow.request
else: else:
if not self.flow.response: if not self.flow.response:
@ -383,25 +362,25 @@ class FlowView(urwid.WidgetWrap):
self.set_query, message self.set_query, message
) )
) )
elif part == "u" and self.state.view_flow_mode == common.VIEW_FLOW_REQUEST: elif part == "u" and self.tab_offset == TAB_REQ:
signals.status_prompt.send( signals.status_prompt.send(
prompt = "URL", prompt = "URL",
text = message.url, text = message.url,
callback = self.set_url callback = self.set_url
) )
elif part == "m" and self.state.view_flow_mode == common.VIEW_FLOW_REQUEST: elif part == "m" and self.tab_offset == TAB_REQ:
signals.status_prompt_onekey.send( signals.status_prompt_onekey.send(
prompt = "Method", prompt = "Method",
keys = common.METHOD_OPTIONS, keys = common.METHOD_OPTIONS,
callback = self.edit_method callback = self.edit_method
) )
elif part == "c" and self.state.view_flow_mode == common.VIEW_FLOW_RESPONSE: elif part == "c" and self.tab_offset == TAB_RESP:
signals.status_prompt.send( signals.status_prompt.send(
prompt = "Code", prompt = "Code",
text = str(message.code), text = str(message.code),
callback = self.set_resp_code callback = self.set_resp_code
) )
elif part == "m" and self.state.view_flow_mode == common.VIEW_FLOW_RESPONSE: elif part == "m" and self.tab_offset == TAB_RESP:
signals.status_prompt.send( signals.status_prompt.send(
prompt = "Message", prompt = "Message",
text = message.msg, text = message.msg,
@ -422,7 +401,7 @@ class FlowView(urwid.WidgetWrap):
signals.status_message.send(message="No more flows!") signals.status_message.send(message="No more flows!")
else: else:
signals.pop_view_state.send(self) signals.pop_view_state.send(self)
self.master.view_flow(new_flow) self.master.view_flow(new_flow, self.tab_offset)
def view_next_flow(self, flow): def view_next_flow(self, flow):
return self._view_nextprev_flow("next", flow) return self._view_nextprev_flow("next", flow)
@ -433,7 +412,7 @@ class FlowView(urwid.WidgetWrap):
def change_this_display_mode(self, t): def change_this_display_mode(self, t):
self.state.add_flow_setting( self.state.add_flow_setting(
self.flow, self.flow,
(self.state.view_flow_mode, "prettyview"), (self.tab_offset, "prettyview"),
contentview.get_by_shortcut(t) contentview.get_by_shortcut(t)
) )
signals.flow_change.send(self, flow = self.flow) signals.flow_change.send(self, flow = self.flow)
@ -443,7 +422,7 @@ class FlowView(urwid.WidgetWrap):
val = CONTENT_MISSING val = CONTENT_MISSING
else: else:
val = None val = None
if self.state.view_flow_mode == common.VIEW_FLOW_REQUEST: if self.tab_offset == TAB_REQ:
self.flow.request.content = val self.flow.request.content = val
else: else:
self.flow.response.content = val self.flow.response.content = val
@ -455,7 +434,7 @@ class FlowView(urwid.WidgetWrap):
return return
key = common.shortcuts(key) key = common.shortcuts(key)
if self.state.view_flow_mode == common.VIEW_FLOW_REQUEST: if self.tab_offset == TAB_REQ:
conn = self.flow.request conn = self.flow.request
else: else:
conn = self.flow.response conn = self.flow.response
@ -463,11 +442,6 @@ class FlowView(urwid.WidgetWrap):
if key == "q": if key == "q":
signals.pop_view_state.send(self) signals.pop_view_state.send(self)
return None return None
elif key == "tab":
if self.state.view_flow_mode == common.VIEW_FLOW_REQUEST:
self.view_response()
else:
self.view_request()
elif key in ("up", "down", "page up", "page down"): elif key in ("up", "down", "page up", "page down"):
# Why doesn't this just work?? # Why doesn't this just work??
self._w.keypress(size, key) self._w.keypress(size, key)
@ -478,7 +452,7 @@ class FlowView(urwid.WidgetWrap):
self.master.accept_all() self.master.accept_all()
self.master.view_flow(self.flow) self.master.view_flow(self.flow)
elif key == "b": elif key == "b":
if self.state.view_flow_mode == common.VIEW_FLOW_REQUEST: if self.tab_offset == TAB_REQ:
common.ask_save_body("q", self.master, self.state, self.flow) common.ask_save_body("q", self.master, self.state, self.flow)
else: else:
common.ask_save_body("s", self.master, self.state, self.flow) common.ask_save_body("s", self.master, self.state, self.flow)
@ -497,7 +471,7 @@ class FlowView(urwid.WidgetWrap):
self.master.view_flow(f) self.master.view_flow(f)
signals.status_message.send(message="Duplicated.") signals.status_message.send(message="Duplicated.")
elif key == "e": elif key == "e":
if self.state.view_flow_mode == common.VIEW_FLOW_REQUEST: if self.tab_offset == TAB_REQ:
signals.status_prompt_onekey.send( signals.status_prompt_onekey.send(
prompt = "Edit request", prompt = "Edit request",
keys = ( keys = (
@ -527,13 +501,13 @@ class FlowView(urwid.WidgetWrap):
signals.status_message.send(message="Loading all body data...") signals.status_message.send(message="Loading all body data...")
self.state.add_flow_setting( self.state.add_flow_setting(
self.flow, self.flow,
(self.state.view_flow_mode, "fullcontents"), (self.tab_state, "fullcontents"),
True True
) )
signals.flow_change.send(self, flow = self.flow) signals.flow_change.send(self, flow = self.flow)
signals.status_message.send(message="") signals.status_message.send(message="")
elif key == "g": elif key == "g":
if self.state.view_flow_mode == common.VIEW_FLOW_REQUEST: if self.tab_offset == TAB_REQ:
scope = "q" scope = "q"
else: else:
scope = "s" scope = "s"

35
libmproxy/console/tabs.py Normal file
View File

@ -0,0 +1,35 @@
import urwid
class Tabs(urwid.WidgetWrap):
def __init__(self, tabs, tab_offset=0):
urwid.WidgetWrap.__init__(self, "")
self.tab_offset = tab_offset
self.tabs = tabs
self.show()
def _tab(self, content, attr):
p = urwid.Text(content)
p = urwid.Padding(p, align="left", width=("relative", 100))
p = urwid.AttrWrap(p, attr)
return p
def keypress(self, size, key):
if key == "tab":
self.tab_offset = (self.tab_offset + 1)%(len(self.tabs))
self.show()
else:
return key
def show(self):
headers = []
for i in range(len(self.tabs)):
txt = self.tabs[i][0]()
if i == self.tab_offset:
headers.append(self._tab(txt, "heading"))
else:
headers.append(self._tab(txt, "heading_inactive"))
headers = urwid.Columns(headers)
self._w = urwid.Frame(
body = self.tabs[self.tab_offset][1](),
header = headers
)