File 2227-observer-re-store-config.patch of Package erlang

From 1f205a59ab61f159920b41d5f17f207299cb7a8c Mon Sep 17 00:00:00 2001
From: Dan Gudmundsson <dgud@erlang.org>
Date: Mon, 27 Mar 2017 17:03:52 +0200
Subject: [PATCH 5/5] observer: (re)store config

Store config when exiting app and restore config when starting again.
---
 lib/observer/src/observer_alloc_wx.erl | 22 +++++++----
 lib/observer/src/observer_app_wx.erl   | 10 +++--
 lib/observer/src/observer_lib.erl      | 13 ++++++-
 lib/observer/src/observer_perf_wx.erl  | 18 ++++++---
 lib/observer/src/observer_port_wx.erl  | 15 ++++---
 lib/observer/src/observer_pro_wx.erl   | 34 ++++++++++------
 lib/observer/src/observer_sys_wx.erl   | 13 ++++---
 lib/observer/src/observer_trace_wx.erl | 71 ++++++++++++++++++++--------------
 lib/observer/src/observer_tv_wx.erl    | 23 ++++++++---
 lib/observer/src/observer_wx.erl       | 45 ++++++++++++++++-----
 10 files changed, 178 insertions(+), 86 deletions(-)

diff --git a/lib/observer/src/observer_alloc_wx.erl b/lib/observer/src/observer_alloc_wx.erl
index cad02087b..9e1442a5c 100644
--- a/lib/observer/src/observer_alloc_wx.erl
+++ b/lib/observer/src/observer_alloc_wx.erl
@@ -18,7 +18,7 @@
 %% %CopyrightEnd%
 -module(observer_alloc_wx).
 
--export([start_link/2]).
+-export([start_link/3]).
 
 %% wx_object callbacks
 -export([init/1, handle_info/2, terminate/2, code_change/3, handle_call/3,
@@ -49,10 +49,10 @@
 	[make_win/4, setup_graph_drawing/1, refresh_panel/4, interval_dialog/2,
 	 add_data/5, precalc/4]).
 
-start_link(Notebook, Parent) ->
-    wx_object:start_link(?MODULE, [Notebook, Parent], []).
+start_link(Notebook, Parent, Config) ->
+    wx_object:start_link(?MODULE, [Notebook, Parent, Config], []).
 
-init([Notebook, Parent]) ->
+init([Notebook, Parent, Config]) ->
     try
 	TopP  = wxPanel:new(Notebook),
 	Main  = wxBoxSizer:new(?wxVERTICAL),
@@ -75,7 +75,7 @@ init([Notebook, Parent]) ->
 		      wins  = Windows,
 		      mem   = MemWin,
 		      paint = PaintInfo,
-		      time  = setup_time(),
+		      time  = setup_time(Config),
                       max   = #{}
 		     }
 	}
@@ -84,9 +84,11 @@ init([Notebook, Parent]) ->
 	    {stop, Err}
     end.
 
-setup_time() ->
-    Freq = 1,
-    #ti{fetch=Freq, disp=?DISP_FREQ/Freq}.
+setup_time(Config) ->
+    Freq = maps:get(fetch, Config, 1),
+    #ti{disp=?DISP_FREQ/Freq,
+        fetch=Freq,
+        secs=maps:get(secs, Config, ?DISP_SECONDS)}.
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 handle_event(#wx{id=?ID_REFRESH_INTERVAL, event=#wxCommand{type=command_menu_selected}},
@@ -117,6 +119,10 @@ handle_sync_event(#wx{obj=Panel, event = #wxPaint{}},_,
     refresh_panel(Active, Win, Ti, Paint),
     ok.
 %%%%%%%%%%
+handle_call(get_config, _, #state{time=Ti}=State) ->
+    #ti{fetch=Fetch, secs=Range} = Ti,
+    {reply, #{fetch=>Fetch, secs=>Range}, State};
+
 handle_call(Event, From, _State) ->
     error({unhandled_call, Event, From}).
 
diff --git a/lib/observer/src/observer_app_wx.erl b/lib/observer/src/observer_app_wx.erl
index 80a41fdde..63ca3aeba 100644
--- a/lib/observer/src/observer_app_wx.erl
+++ b/lib/observer/src/observer_app_wx.erl
@@ -18,7 +18,7 @@
 %% %CopyrightEnd%
 -module(observer_app_wx).
 
--export([start_link/2]).
+-export([start_link/3]).
 
 %% wx_object callbacks
 -export([init/1, handle_info/2, terminate/2, code_change/3, handle_call/3,
@@ -73,10 +73,10 @@
 
 -define(wxGC, wxGraphicsContext).
 
-start_link(Notebook, Parent) ->
-    wx_object:start_link(?MODULE, [Notebook, Parent], []).
+start_link(Notebook, Parent, Config) ->
+    wx_object:start_link(?MODULE, [Notebook, Parent, Config], []).
 
-init([Notebook, Parent]) ->
+init([Notebook, Parent, _Config]) ->
     Panel = wxPanel:new(Notebook, [{size, wxWindow:getClientSize(Notebook)},
 				   {winid, 1}
 				  ]),
@@ -258,6 +258,8 @@ handle_sync_event(#wx{event = #wxPaint{}},_,
     destroy_gc(GC),
     ok.
 %%%%%%%%%%
+handle_call(get_config, _, State) ->
+    {reply, #{}, State};
 handle_call(Event, From, _State) ->
     error({unhandled_call, Event, From}).
 
diff --git a/lib/observer/src/observer_lib.erl b/lib/observer/src/observer_lib.erl
index 47844c130..68095d7f5 100644
--- a/lib/observer/src/observer_lib.erl
+++ b/lib/observer/src/observer_lib.erl
@@ -24,7 +24,7 @@
 	 display_progress_dialog/2, destroy_progress_dialog/0,
 	 wait_for_progress/0, report_progress/1,
 	 user_term/3, user_term_multiline/3,
-	 interval_dialog/4, start_timer/1, stop_timer/1,
+	 interval_dialog/4, start_timer/1, start_timer/2, stop_timer/1, timer_config/1,
 	 display_info/2, display_info/3, fill_info/2, update_info/2, to_str/1,
 	 create_menus/3, create_menu_item/3,
 	 create_attrs/0,
@@ -90,6 +90,12 @@ stop_timer(Timer = {true, _}) -> Timer;
 stop_timer(Timer = {_, Intv}) ->
     setup_timer(false, Timer),
     {true, Intv}.
+
+start_timer(#{interval:=Intv}, _Def) ->
+    setup_timer(true, {false, Intv});
+start_timer(_, Def) ->
+    setup_timer(true, {false, Def}).
+
 start_timer(Intv) when is_integer(Intv) ->
     setup_timer(true, {true, Intv});
 start_timer(Timer) ->
@@ -105,6 +111,11 @@ setup_timer(Bool, {Timer, Old}) ->
     timer:cancel(Timer),
     setup_timer(Bool, {false, Old}).
 
+timer_config({_, Interval}) ->
+    #{interval=>Interval};
+timer_config(#{}=Config) ->
+    Config.
+
 display_info_dialog(Parent,Str) ->
     display_info_dialog(Parent,"",Str).
 display_info_dialog(Parent,Title,Str) ->
diff --git a/lib/observer/src/observer_perf_wx.erl b/lib/observer/src/observer_perf_wx.erl
index 0cbcdbceb..fc5fb226d 100644
--- a/lib/observer/src/observer_perf_wx.erl
+++ b/lib/observer/src/observer_perf_wx.erl
@@ -18,7 +18,7 @@
 %% %CopyrightEnd%
 -module(observer_perf_wx).
 
--export([start_link/2]).
+-export([start_link/3]).
 
 %% wx_object callbacks
 -export([init/1, handle_info/2, terminate/2, code_change/3, handle_call/3,
@@ -57,10 +57,10 @@
 
 -record(paint, {font, small, pen, pen2, pens, dot_pens, usegc = false}).
 
-start_link(Notebook, Parent) ->
-    wx_object:start_link(?MODULE, [Notebook, Parent], []).
+start_link(Notebook, Parent, Config) ->
+    wx_object:start_link(?MODULE, [Notebook, Parent, Config], []).
 
-init([Notebook, Parent]) ->
+init([Notebook, Parent, Config]) ->
     try
 	Panel = wxPanel:new(Notebook),
 	Main  = wxBoxSizer:new(?wxVERTICAL),
@@ -81,7 +81,9 @@ init([Notebook, Parent]) ->
 			panel =Panel,
 			wins = Windows,
 			paint=PaintInfo,
-			samples=reset_data()
+			samples=reset_data(),
+                        time=#ti{fetch=maps:get(fetch, Config, ?FETCH_DATA),
+                                 secs=maps:get(secs, Config, ?DISP_SECONDS)}
 		       },
 	{Panel, State0}
     catch _:Err ->
@@ -177,6 +179,10 @@ refresh_panel(Active, #win{name=_Id, panel=Panel}=Win, Ti, #paint{usegc=UseGC}=P
     destroy_gc(GC).
 
 %%%%%%%%%%
+handle_call(get_config, _, #state{time=Ti}=State) ->
+    #ti{fetch=Fetch, secs=Range} = Ti,
+    {reply, #{fetch=>Fetch, secs=>Range}, State};
+
 handle_call(Event, From, _State) ->
     error({unhandled_call, Event, From}).
 
@@ -210,7 +216,7 @@ handle_info({refresh, Seq}, #state{panel=Panel, time=#ti{tick=Seq, disp=DispF}=T
 handle_info({refresh, _}, State) ->
     {noreply, State};
 
-handle_info({active, Node}, #state{parent=Parent, panel=Panel, appmon=Old, time=_Ti} = State) ->
+handle_info({active, Node}, #state{parent=Parent, panel=Panel, appmon=Old} = State) ->
     create_menus(Parent, []),
     try
 	Node = node(Old),
diff --git a/lib/observer/src/observer_port_wx.erl b/lib/observer/src/observer_port_wx.erl
index c87238d82..db5e6ceb3 100644
--- a/lib/observer/src/observer_port_wx.erl
+++ b/lib/observer/src/observer_port_wx.erl
@@ -18,7 +18,7 @@
 %% %CopyrightEnd%
 -module(observer_port_wx).
 
--export([start_link/2]).
+-export([start_link/3]).
 
 %% wx_object callbacks
 -export([init/1, handle_info/2, terminate/2, code_change/3, handle_call/3,
@@ -77,10 +77,10 @@
 	  open_wins=[]
 	}).
 
-start_link(Notebook,  Parent) ->
-    wx_object:start_link(?MODULE, [Notebook, Parent], []).
+start_link(Notebook,  Parent, Config) ->
+    wx_object:start_link(?MODULE, [Notebook, Parent, Config], []).
 
-init([Notebook, Parent]) ->
+init([Notebook, Parent, Config]) ->
     Panel = wxPanel:new(Notebook),
     Sizer = wxBoxSizer:new(?wxVERTICAL),
     Style = ?wxLC_REPORT bor ?wxLC_HRULES,
@@ -110,7 +110,7 @@ init([Notebook, Parent]) ->
     wxListCtrl:connect(Grid, size, [{skip, true}]),
 
     wxWindow:setFocus(Grid),
-    {Panel, #state{grid=Grid, parent=Parent, panel=Panel, timer={false, 10}}}.
+    {Panel, #state{grid=Grid, parent=Parent, panel=Panel, timer=Config}}.
 
 handle_event(#wx{id=?ID_REFRESH},
 	     State = #state{node=Node, grid=Grid, opt=Opt}) ->
@@ -260,6 +260,9 @@ handle_event(Event, _State) ->
 handle_sync_event(_Event, _Obj, _State) ->
     ok.
 
+handle_call(get_config, _, #state{timer=Timer}=State) ->
+    {reply, observer_lib:timer_config(Timer), State};
+
 handle_call(Event, From, _State) ->
     error({unhandled_call, Event, From}).
 
@@ -298,7 +301,7 @@ handle_info({active, Node}, State = #state{parent=Parent, grid=Grid, opt=Opt,
     Ports = update_grid(Grid, sel(State), Opt, Ports0),
     wxWindow:setFocus(Grid),
     create_menus(Parent),
-    Timer = observer_lib:start_timer(Timer0),
+    Timer = observer_lib:start_timer(Timer0, 10),
     {noreply, State#state{node=Node, ports=Ports, timer=Timer}};
 
 handle_info(not_active, State = #state{timer = Timer0}) ->
diff --git a/lib/observer/src/observer_pro_wx.erl b/lib/observer/src/observer_pro_wx.erl
index f07b9e295..3ecf8bdd9 100644
--- a/lib/observer/src/observer_pro_wx.erl
+++ b/lib/observer/src/observer_pro_wx.erl
@@ -20,7 +20,7 @@
 
 -behaviour(wx_object).
 
--export([start_link/2]).
+-export([start_link/3]).
 
 %% wx_object callbacks
 -export([init/1, handle_info/2, terminate/2, code_change/3, handle_call/3,
@@ -86,18 +86,19 @@
 		right_clicked_pid,
 		holder}).
 
-start_link(Notebook, Parent) ->
-    wx_object:start_link(?MODULE, [Notebook, Parent], []).
+start_link(Notebook, Parent, Config) ->
+    wx_object:start_link(?MODULE, [Notebook, Parent, Config], []).
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-init([Notebook, Parent]) ->
+init([Notebook, Parent, Config]) ->
     Attrs = observer_lib:create_attrs(),
     Self = self(),
-    Holder = spawn_link(fun() -> init_table_holder(Self, Attrs) end),
-    {ProPanel, State} = setup(Notebook, Parent, Holder),
+    Acc = maps:get(acc, Config, false),
+    Holder = spawn_link(fun() -> init_table_holder(Self, Acc, Attrs) end),
+    {ProPanel, State} = setup(Notebook, Parent, Holder, Config),
     {ProPanel, State#state{holder=Holder}}.
 
-setup(Notebook, Parent, Holder) ->
+setup(Notebook, Parent, Holder, Config) ->
     ProPanel = wxPanel:new(Notebook, []),
 
     Grid  = create_list_box(ProPanel, Holder),
@@ -113,7 +114,7 @@ setup(Notebook, Parent, Holder) ->
 		   panel=ProPanel,
 		   parent_notebook=Notebook,
 		   holder=Holder,
-		   timer={false, 10}
+		   timer=Config
 		   },
     {ProPanel, State}.
 
@@ -246,7 +247,7 @@ handle_info({active, Node},
 	    #state{holder=Holder, timer=Timer, parent=Parent}=State) ->
     create_pro_menu(Parent, Holder),
     Holder ! {change_node, Node},
-    {noreply, State#state{timer=observer_lib:start_timer(Timer)}};
+    {noreply, State#state{timer=observer_lib:start_timer(Timer, 10)}};
 
 handle_info(not_active, #state{timer=Timer0}=State) ->
     Timer = observer_lib:stop_timer(Timer0),
@@ -264,11 +265,15 @@ terminate(_Reason, #state{holder=Holder}) ->
 code_change(_, _, State) ->
     {ok, State}.
 
+handle_call(get_config, _, #state{holder=Holder, timer=Timer}=State) ->
+    Conf = observer_lib:timer_config(Timer),
+    Accum = call(Holder, {get_accum, self()}),
+    {reply, Conf#{acc=>Accum}, State};
+
 handle_call(Msg, _From, State) ->
     io:format("~p:~p: Unhandled call ~p~n",[?MODULE, ?LINE, Msg]),
     {reply, ok, State}.
 
-
 handle_cast(Msg, State) ->
     io:format("~p:~p: Unhandled cast ~p~n", [?MODULE, ?LINE, Msg]),
     {noreply, State}.
@@ -453,14 +458,19 @@ rm_selected(_, [], [], AccIds, AccPids) ->
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%TABLE HOLDER%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-init_table_holder(Parent, Attrs) ->
+init_table_holder(Parent, Accum0, Attrs) ->
     Backend = spawn_link(node(), observer_backend,etop_collect,[self()]),
+    Accum = case Accum0 of
+                true -> true;
+                false -> []
+            end,
     table_holder(#holder{parent=Parent,
 			 etop=#etop_info{},
 			 info=array:new(),
 			 node=node(),
 			 backend_pid=Backend,
-			 attrs=Attrs
+			 attrs=Attrs,
+                         accum=Accum
 			}).
 
 table_holder(#holder{info=Info, attrs=Attrs,
diff --git a/lib/observer/src/observer_sys_wx.erl b/lib/observer/src/observer_sys_wx.erl
index fa824995f..2529e79e2 100644
--- a/lib/observer/src/observer_sys_wx.erl
+++ b/lib/observer/src/observer_sys_wx.erl
@@ -20,7 +20,7 @@
 
 -behaviour(wx_object).
 
--export([start_link/2]).
+-export([start_link/3]).
 %% wx_object callbacks
 -export([init/1, handle_info/2, terminate/2, code_change/3, handle_call/3,
 	 handle_event/2, handle_cast/2]).
@@ -41,12 +41,12 @@
 	 fields,
 	 timer}).
 
-start_link(Notebook, Parent) ->
-    wx_object:start_link(?MODULE, [Notebook, Parent], []).
+start_link(Notebook, Parent, Config) ->
+    wx_object:start_link(?MODULE, [Notebook, Parent, Config], []).
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-init([Notebook, Parent]) ->
+init([Notebook, Parent, Config]) ->
     SysInfo = observer_backend:sys_info(),
     {Sys, Mem, Cpu, Stats} = info_fields(),
     Panel = wxPanel:new(Notebook),
@@ -69,7 +69,7 @@ init([Notebook, Parent]) ->
     wxSizer:add(Sizer, HSizer1, [{flag, ?wxEXPAND bor BorderFlags bor ?wxBOTTOM},
 				 {proportion, 0}, {border, 5}]),
     wxPanel:setSizer(Panel, Sizer),
-    Timer = observer_lib:start_timer(10),
+    Timer = observer_lib:start_timer(Config, 10),
     {Panel, #sys_wx_state{parent=Parent,
 			  parent_notebook=Notebook,
 			  panel=Panel, sizer=Sizer,
@@ -167,6 +167,9 @@ terminate(_Reason, _State) ->
 code_change(_, _, State) ->
     {ok, State}.
 
+handle_call(get_config, _, #sys_wx_state{timer=Timer}=State) ->
+    {reply, observer_lib:timer_config(Timer), State};
+
 handle_call(Msg, _From, State) ->
     io:format("~p~p: Unhandled Call ~p~n",[?MODULE, ?LINE, Msg]),
     {reply, ok, State}.
diff --git a/lib/observer/src/observer_trace_wx.erl b/lib/observer/src/observer_trace_wx.erl
index af90e2100..247a4608d 100644
--- a/lib/observer/src/observer_trace_wx.erl
+++ b/lib/observer/src/observer_trace_wx.erl
@@ -19,7 +19,7 @@
 
 -module(observer_trace_wx).
 
--export([start_link/2, add_processes/1, add_ports/1]).
+-export([start_link/3, add_processes/1, add_ports/1]).
 -export([init/1, handle_info/2, terminate/2, code_change/3, handle_call/3,
 	 handle_event/2, handle_cast/2]).
 
@@ -88,8 +88,8 @@
 
 -record(titem, {id, opts}).
 
-start_link(Notebook, ParentPid) ->
-    wx_object:start_link(?MODULE, [Notebook, ParentPid], []).
+start_link(Notebook, ParentPid, Config) ->
+    wx_object:start_link(?MODULE, [Notebook, ParentPid, Config], []).
 
 add_processes(Pids) when is_list(Pids) ->
     wx_object:cast(observer_wx:get_tracer(), {add_processes, Pids}).
@@ -99,10 +99,10 @@ add_ports(Ports) when is_list(Ports) ->
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-init([Notebook, ParentPid]) ->
-    wx:batch(fun() -> create_window(Notebook, ParentPid) end).
+init([Notebook, ParentPid, Config]) ->
+    wx:batch(fun() -> create_window(Notebook, ParentPid, Config) end).
 
-create_window(Notebook, ParentPid) ->
+create_window(Notebook, ParentPid, Config) ->
     %% Create the window
     Panel = wxPanel:new(Notebook, [{size, wxWindow:getClientSize(Notebook)}]),
     Sizer = wxBoxSizer:new(?wxVERTICAL),
@@ -130,11 +130,16 @@ create_window(Notebook, ParentPid) ->
     wxSizer:add(Sizer, Buttons, [{flag, ?wxLEFT bor ?wxRIGHT bor ?wxDOWN},
 				 {border, 5}, {proportion,0}]),
     wxWindow:setSizer(Panel, Sizer),
+    MS = parse_ms(maps:get(match_specs, Config, []), default_matchspecs()),
     {Panel, #state{parent=ParentPid, panel=Panel,
 		   n_view=NodeView, proc_view=ProcessView, port_view=PortView,
 		   m_view=ModView, f_view=FuncView,
 		   toggle_button = ToggleButton,
-		   match_specs=default_matchspecs()}}.
+                   output=maps:get(output, Config, []),
+                   def_proc_flags=maps:get(procflags, Config, []),
+                   def_port_flags=maps:get(portflags, Config, []),
+                   match_specs=MS
+                  }}.
 
 default_matchspecs() ->
     [{Key,default_matchspecs(Key)} || Key <- [funcs,send,'receive']].
@@ -397,27 +402,19 @@ handle_event(#wx{id=?LOG_SAVE, userData=TCtrl}, #state{panel=Panel} = State) ->
     {noreply, State};
 
 handle_event(#wx{id = ?SAVE_TRACEOPTS},
-	     #state{panel = Panel,
-		    def_proc_flags = ProcFlags,
-		    def_port_flags = PortFlags,
-		    match_specs = MatchSpecs,
-		    tpatterns = TracePatterns,
-		    output = Output
-		   } = State) ->
+	     #state{panel = Panel} = State) ->
     Dialog = wxFileDialog:new(Panel, [{style, ?wxFD_SAVE bor ?wxFD_OVERWRITE_PROMPT}]),
     case wxFileDialog:showModal(Dialog) of
 	?wxID_OK ->
 	    Path = wxFileDialog:getPath(Dialog),
-	    write_file(Panel, Path,
-		       ProcFlags, PortFlags, MatchSpecs, Output,
-		       dict:to_list(TracePatterns)
-		      );
+	    write_file(Panel, Path, get_config(State));
 	_ ->
 	    ok
     end,
     wxDialog:destroy(Dialog),
     {noreply, State};
 
+
 handle_event(#wx{id = ?LOAD_TRACEOPTS}, #state{panel = Panel} = State) ->
     Dialog = wxFileDialog:new(Panel, [{style, ?wxFD_FILE_MUST_EXIST}]),
     State2 = case wxFileDialog:showModal(Dialog) of
@@ -690,6 +687,10 @@ handle_event(#wx{id=ID, event = What}, State) ->
     {noreply, State}.
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+handle_call(get_config, _, State) ->
+    Config0 = get_config(State),
+    Config = lists:keydelete(trace_p, 1, Config0),
+    {reply, maps:from_list(Config), State};
 handle_call(Msg, From, _State) ->
     error({unhandled_call, Msg, From}).
 
@@ -1101,26 +1102,38 @@ ftup(Trace, Index, Size) ->
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-write_file(Frame, Filename, ProcFlags, PortFlags, MatchSpecs, Output, TPs) ->
+get_config(#state{def_proc_flags = ProcFlags,
+                  def_port_flags = PortFlags,
+                  match_specs = MatchSpecs0,
+                  tpatterns = TracePatterns,
+                  output = Output}) ->
     MSToList = fun(#match_spec{name=Id, term=T, func=F}) ->
 		       [{name,Id},{term,T},{func,F}]
 	       end,
-    MSTermList = [{ms,Key,[MSToList(MS) || MS <- MSs]} ||
-		     {Key,MSs} <- MatchSpecs],
+    MatchSpecs = [{ms,Key,[MSToList(MS) || MS <- MSs]} ||
+		     {Key,MSs} <- MatchSpecs0],
     TPToTuple = fun(#tpattern{fa={F,A}, ms=Ms}) ->
-		       {F,A,MSToList(Ms)}
+                        {F,A,MSToList(Ms)}
 		end,
     ModuleTermList = [{tp, Module, [TPToTuple(FTP) || FTP <- FTPs]} ||
-			 {Module,FTPs} <- TPs],
-
+			 {Module,FTPs} <- dict:to_list(TracePatterns)],
+    [{procflags,ProcFlags},
+     {portflags,PortFlags},
+     {match_specs,MatchSpecs},
+     {output,Output},
+     {trace_p,ModuleTermList}].
+
+write_file(Frame, Filename, Config) ->
     Str =
 	["%%%\n%%% This file is generated by Observer\n",
 	 "%%%\n%%% DO NOT EDIT!\n%%%\n",
-	 [io_lib:format("~p.~n",[MSTerm]) || MSTerm <- MSTermList],
-	 io_lib:format("~p.~n",[{procflags,ProcFlags}]),
-	 io_lib:format("~p.~n",[{portflags,PortFlags}]),
-	 io_lib:format("~p.~n",[{output,Output}]),
-	 [io_lib:format("~p.~n",[ModuleTerm]) || ModuleTerm <- ModuleTermList]
+	 [io_lib:format("~p.~n",[MSTerm]) ||
+             MSTerm <- proplists:get_value(match_specs, Config)],
+	 io_lib:format("~p.~n",[lists:keyfind(procflags, 1, Config)]),
+	 io_lib:format("~p.~n",[lists:keyfind(portflags, 1, Config)]),
+	 io_lib:format("~p.~n",[lists:keyfind(output, 1, Config)]),
+	 [io_lib:format("~p.~n",[ModuleTerm]) ||
+             ModuleTerm <- proplists:get_value(trace_p, Config)]
 	],
 
     case file:write_file(Filename, list_to_binary(Str)) of
diff --git a/lib/observer/src/observer_tv_wx.erl b/lib/observer/src/observer_tv_wx.erl
index b66d882f7..e112c5453 100644
--- a/lib/observer/src/observer_tv_wx.erl
+++ b/lib/observer/src/observer_tv_wx.erl
@@ -18,7 +18,7 @@
 %% %CopyrightEnd%
 -module(observer_tv_wx).
 
--export([start_link/2, display_table_info/4]).
+-export([start_link/3, display_table_info/4]).
 
 %% wx_object callbacks
 -export([init/1, handle_info/2, terminate/2, code_change/3, handle_call/3,
@@ -58,10 +58,10 @@
 	  timer
 	}).
 
-start_link(Notebook,  Parent) ->
-    wx_object:start_link(?MODULE, [Notebook, Parent], []).
+start_link(Notebook,  Parent, Config) ->
+    wx_object:start_link(?MODULE, [Notebook, Parent, Config], []).
 
-init([Notebook, Parent]) ->
+init([Notebook, Parent, Config]) ->
     Panel = wxPanel:new(Notebook),
     Sizer = wxBoxSizer:new(?wxVERTICAL),
     Style = ?wxLC_REPORT bor ?wxLC_SINGLE_SEL bor ?wxLC_HRULES,
@@ -94,7 +94,12 @@ init([Notebook, Parent]) ->
     wxListCtrl:connect(Grid, size, [{skip, true}]),
 
     wxWindow:setFocus(Grid),
-    {Panel, #state{grid=Grid, parent=Parent, panel=Panel, timer={false, 10}}}.
+    {Panel, #state{grid=Grid, parent=Parent, panel=Panel,
+                   timer=Config,
+                   opt=#opt{type=maps:get(type, Config, ets),
+                            sys_hidden=maps:get(sys_hidden, Config, true),
+                            unread_hidden=maps:get(unread_hidden, Config, true)}
+                  }}.
 
 handle_event(#wx{id=?ID_REFRESH},
 	     State = #state{node=Node, grid=Grid, opt=Opt}) ->
@@ -203,6 +208,12 @@ handle_event(Event, _State) ->
 handle_sync_event(_Event, _Obj, _State) ->
     ok.
 
+handle_call(get_config, _, #state{timer=Timer, opt=Opt}=State) ->
+    #opt{type=Type, sys_hidden=Sys, unread_hidden=Unread} = Opt,
+    Conf0 = observer_lib:timer_config(Timer),
+    Conf = Conf0#{type=>Type, sys_hidden=>Sys, unread_hidden=>Unread},
+    {reply, Conf, State};
+
 handle_call(Event, From, _State) ->
     error({unhandled_call, Event, From}).
 
@@ -233,7 +244,7 @@ handle_info({active, Node}, State = #state{parent=Parent, grid=Grid, opt=Opt0,
     {Tabs,Sel} = update_grid(Grid, sel(State), Opt, Tables),
     wxWindow:setFocus(Grid),
     create_menus(Parent, Opt),
-    Timer = observer_lib:start_timer(Timer0),
+    Timer = observer_lib:start_timer(Timer0, 10),
     {noreply, State#state{node=Node, tabs=Tabs, timer=Timer, opt=Opt, selected=Sel}};
 
 handle_info(not_active, State = #state{timer = Timer0}) ->
diff --git a/lib/observer/src/observer_wx.erl b/lib/observer/src/observer_wx.erl
index 83038620c..0a591babd 100644
--- a/lib/observer/src/observer_wx.erl
+++ b/lib/observer/src/observer_wx.erl
@@ -60,7 +60,8 @@
 	 nodes,
 	 prev_node="",
 	 log = false,
-	 reply_to=false
+	 reply_to=false,
+         config
 	}).
 
 start() ->
@@ -111,6 +112,10 @@ init(_Args) ->
 
 setup(#state{frame = Frame} = State) ->
     %% Setup Menubar & Menus
+    Config = load_config(),
+    Cnf = fun(Who) ->
+                  proplists:get_value(Who, Config, #{})
+          end,
     MenuBar = wxMenuBar:new(),
 
     {Nodes, NodeMenus} = get_nodes(),
@@ -124,7 +129,7 @@ setup(#state{frame = Frame} = State) ->
     Notebook = wxNotebook:new(Panel, ?ID_NOTEBOOK, [{style, ?wxBK_DEFAULT}]),
 
     %% System Panel
-    SysPanel = observer_sys_wx:start_link(Notebook, self()),
+    SysPanel = observer_sys_wx:start_link(Notebook, self(), Cnf(sys_panel)),
     wxNotebook:addPage(Notebook, SysPanel, "System", []),
 
     %% Setup sizer create early to get it when window shows
@@ -151,31 +156,31 @@ setup(#state{frame = Frame} = State) ->
     %% the window size
 
     %% Perf Viewer Panel
-    PerfPanel = observer_perf_wx:start_link(Notebook, self()),
+    PerfPanel = observer_perf_wx:start_link(Notebook, self(), Cnf(perf_panel)),
     wxNotebook:addPage(Notebook, PerfPanel, "Load Charts", []),
 
     %% Memory Allocator Viewer Panel
-    AllcPanel = observer_alloc_wx:start_link(Notebook, self()),
+    AllcPanel = observer_alloc_wx:start_link(Notebook, self(), Cnf(allc_panel)),
     wxNotebook:addPage(Notebook, AllcPanel, ?ALLOC_STR, []),
 
     %% App Viewer Panel
-    AppPanel = observer_app_wx:start_link(Notebook, self()),
+    AppPanel = observer_app_wx:start_link(Notebook, self(), Cnf(app_panel)),
     wxNotebook:addPage(Notebook, AppPanel, "Applications", []),
 
     %% Process Panel
-    ProPanel = observer_pro_wx:start_link(Notebook, self()),
+    ProPanel = observer_pro_wx:start_link(Notebook, self(), Cnf(pro_panel)),
     wxNotebook:addPage(Notebook, ProPanel, "Processes", []),
 
     %% Port Panel
-    PortPanel = observer_port_wx:start_link(Notebook, self()),
+    PortPanel = observer_port_wx:start_link(Notebook, self(), Cnf(port_panel)),
     wxNotebook:addPage(Notebook, PortPanel, "Ports", []),
 
     %% Table Viewer Panel
-    TVPanel = observer_tv_wx:start_link(Notebook, self()),
+    TVPanel = observer_tv_wx:start_link(Notebook, self(), Cnf(tv_panel)),
     wxNotebook:addPage(Notebook, TVPanel, "Table Viewer", []),
 
     %% Trace Viewer Panel
-    TracePanel = observer_trace_wx:start_link(Notebook, self()),
+    TracePanel = observer_trace_wx:start_link(Notebook, self(), Cnf(trace_panel)),
     wxNotebook:addPage(Notebook, TracePanel, ?TRACE_STR, []),
 
     %% Force redraw (windows needs it)
@@ -466,6 +471,7 @@ handle_info(_Info, State) ->
 stop_servers(#state{node=Node, log=LogOn, panels=Panels} = _State) ->
     LogOn andalso rpc:block_call(Node, rb, stop, []),
     Me = self(),
+    save_config(Panels),
     Stop = fun() ->
 		   try
 		       _ = [wx_object:stop(Panel) || {_, Panel, _} <- Panels],
@@ -485,6 +491,27 @@ terminate(_Reason, #state{frame = Frame, reply_to=From}) ->
     end,
     ok.
 
+load_config() ->
+    case file:consult(config_file()) of
+        {ok, Config} -> Config;
+        _ -> []
+    end.
+
+save_config(Panels) ->
+    Configs = [{Name, wx_object:call(Panel, get_config)} || {Name, Panel, _} <- Panels],
+    File = config_file(),
+    case filelib:ensure_dir(File) of
+        ok ->
+            Format = [io_lib:format("~p.~n",[Conf]) || Conf <- Configs],
+            _ = file:write_file(File, Format);
+        _ ->
+            ignore
+    end.
+
+config_file() ->
+    Dir = filename:basedir(user_config, "erl_observer"),
+    filename:join(Dir, "config.txt").
+
 code_change(_, _, State) ->
     {ok, State}.
 
-- 
2.12.2

openSUSE Build Service is sponsored by