ui: indicate real mode and toggle it with R key (#354)
There is a limitation/bug: disabling real mode in the transaction screen won't show the non-real postings if it was entered from a real-mode register screen.
This commit is contained in:
		
							parent
							
								
									788021f5a4
								
							
						
					
					
						commit
						509f55864d
					
				| @ -24,6 +24,7 @@ module Hledger.Data.Journal ( | ||||
|   filterJournalPostings, | ||||
|   filterJournalAmounts, | ||||
|   filterTransactionAmounts, | ||||
|   filterTransactionPostings, | ||||
|   filterPostingAmount, | ||||
|   -- * Querying | ||||
|   journalAccountNames, | ||||
| @ -313,6 +314,10 @@ filterTransactionAmounts q t@Transaction{tpostings=ps} = t{tpostings=map (filter | ||||
| filterPostingAmount :: Query -> Posting -> Posting | ||||
| filterPostingAmount q p@Posting{pamount=Mixed as} = p{pamount=Mixed $ filter (q `matchesAmount`) as} | ||||
| 
 | ||||
| filterTransactionPostings :: Query -> Transaction -> Transaction | ||||
| filterTransactionPostings m t@Transaction{tpostings=ps} = t{tpostings=filter (m `matchesPosting`) ps} | ||||
| 
 | ||||
| 
 | ||||
| {- | ||||
| ------------------------------------------------------------------------------- | ||||
| -- filtering V1 | ||||
|  | ||||
| @ -218,9 +218,6 @@ summarisePostingAccounts ps = | ||||
|     displayps | null realps = ps | ||||
|               | otherwise   = realps | ||||
| 
 | ||||
| filterTransactionPostings :: Query -> Transaction -> Transaction | ||||
| filterTransactionPostings m t@Transaction{tpostings=ps} = t{tpostings=filter (m `matchesPosting`) ps} | ||||
| 
 | ||||
| ------------------------------------------------------------------------------- | ||||
| 
 | ||||
| -- | Split a transactions report whose items may involve several commodities, | ||||
|  | ||||
| @ -100,13 +100,15 @@ initAccountsScreen d st@AppState{ | ||||
| initAccountsScreen _ _ = error "init function called with wrong screen type, should not happen" | ||||
| 
 | ||||
| drawAccountsScreen :: AppState -> [Widget] | ||||
| drawAccountsScreen _st@AppState{aopts=uopts, ajournal=j, aScreen=AccountsScreen{asState=(l,_)}} = | ||||
| drawAccountsScreen AppState{aopts=UIOpts{cliopts_=CliOpts{reportopts_=ropts}} | ||||
|                            ,ajournal=j | ||||
|                            ,aScreen=AccountsScreen{asState=(l,_)}} = | ||||
|   [ui] | ||||
|     where | ||||
|       toplabel = files | ||||
|               <+> str " accounts" | ||||
|               <+> borderQueryStr querystr | ||||
|               <+> cleared | ||||
|               <+> togglefilters | ||||
|               <+> borderDepthStr mdepth | ||||
|               <+> str " (" | ||||
|               <+> cur | ||||
| @ -118,11 +120,15 @@ drawAccountsScreen _st@AppState{aopts=uopts, ajournal=j, aScreen=AccountsScreen{ | ||||
|                      f:_ -> withAttr ("border" <> "bold") $ str $ takeFileName f | ||||
|                      -- [f,_:[]] -> (withAttr ("border" <> "bold") $ str $ takeFileName f) <+> str " (& 1 included file)" | ||||
|                      -- f:fs  -> (withAttr ("border" <> "bold") $ str $ takeFileName f) <+> str (" (& " ++ show (length fs) ++ " included files)") | ||||
|       querystr = query_ $ reportopts_ $ cliopts_ uopts | ||||
|       mdepth = depth_ $ reportopts_ $ cliopts_ uopts | ||||
|       cleared = if (cleared_ $ reportopts_ $ cliopts_ uopts) | ||||
|                 then str " with " <+> withAttr (borderAttr <> "query") (str "cleared") <+> str " txns" | ||||
|                 else str "" | ||||
|       querystr = query_ ropts | ||||
|       mdepth = depth_ ropts | ||||
|       togglefilters = | ||||
|         case concat [ | ||||
|              if cleared_ ropts then ["cleared"] else [] | ||||
|             ,if real_ ropts then ["real"] else [] | ||||
|             ] of | ||||
|           [] -> str "" | ||||
|           fs -> str " with " <+> withAttr (borderAttr <> "query") (str $ intercalate ", " fs) <+> str " txns" | ||||
|       cur = str (case l^.listSelectedL of | ||||
|                   Nothing -> "-" | ||||
|                   Just i -> show (i + 1)) | ||||
| @ -133,6 +139,7 @@ drawAccountsScreen _st@AppState{aopts=uopts, ajournal=j, aScreen=AccountsScreen{ | ||||
|          ("-=1234567890", "depth") | ||||
|         ,("F", "flat?") | ||||
|         ,("C", "cleared?") | ||||
|         ,("R", "real?") | ||||
|         ,("right/enter", "register") | ||||
|         ,("g", "reload") | ||||
|         ,("q", "quit") | ||||
| @ -249,6 +256,7 @@ handleAccountsScreen st@AppState{ | ||||
|         Vty.EvKey (Vty.KChar '0') [] -> continue $ reload j d $ setDepth 0 st' | ||||
|         Vty.EvKey (Vty.KChar 'F') [] -> continue $ reload j d $ stToggleFlat st' | ||||
|         Vty.EvKey (Vty.KChar 'C') [] -> continue $ reload j d $ stToggleCleared st' | ||||
|         Vty.EvKey (Vty.KChar 'R') [] -> continue $ reload j d $ stToggleReal st' | ||||
|         Vty.EvKey (Vty.KLeft) []     -> continue $ popScreen st' | ||||
|         Vty.EvKey (k) [] | k `elem` [Vty.KRight, Vty.KEnter] -> do | ||||
|           let | ||||
| @ -264,15 +272,6 @@ handleAccountsScreen st@AppState{ | ||||
|                                  -- continue =<< handleEventLensed st' someLens ev | ||||
| handleAccountsScreen _ _ = error "event handler called with wrong screen type, should not happen" | ||||
| 
 | ||||
| stToggleFlat :: AppState -> AppState | ||||
| stToggleFlat st@AppState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} = | ||||
|   st{aopts=uopts{cliopts_=copts{reportopts_=toggleFlatMode ropts}}} | ||||
| 
 | ||||
| -- | Toggle between flat and tree mode. If in the third "default" mode, go to flat mode. | ||||
| toggleFlatMode :: ReportOpts -> ReportOpts | ||||
| toggleFlatMode ropts@ReportOpts{accountlistmode_=ALFlat} = ropts{accountlistmode_=ALTree} | ||||
| toggleFlatMode ropts = ropts{accountlistmode_=ALFlat} | ||||
| 
 | ||||
| -- | Get the maximum account depth in the current journal. | ||||
| maxDepth :: AppState -> Int | ||||
| maxDepth AppState{ajournal=j} = maximum $ map accountNameLevel $ journalAccountNames j | ||||
|  | ||||
| @ -85,11 +85,11 @@ initRegisterScreen d st@AppState{aopts=opts, ajournal=j, aScreen=s@RegisterScree | ||||
| initRegisterScreen _ _ = error "init function called with wrong screen type, should not happen" | ||||
| 
 | ||||
| drawRegisterScreen :: AppState -> [Widget] | ||||
| drawRegisterScreen AppState{aopts=uopts -- @UIOpts{cliopts_=_copts@CliOpts{reportopts_=_ropts@ReportOpts{query_=querystr}} | ||||
| drawRegisterScreen AppState{aopts=UIOpts{cliopts_=CliOpts{reportopts_=ropts}} | ||||
|                            ,aScreen=RegisterScreen{rsState=(l,acct)}} = [ui] | ||||
|   where | ||||
|     toplabel = withAttr ("border" <> "bold") (str $ T.unpack acct) | ||||
|             <+> cleared | ||||
|             <+> togglefilters | ||||
|             <+> str " transactions" | ||||
|             -- <+> borderQueryStr querystr -- no, account transactions report shows all transactions in the acct ? | ||||
|             -- <+> str " and subs" | ||||
| @ -98,9 +98,13 @@ drawRegisterScreen AppState{aopts=uopts -- @UIOpts{cliopts_=_copts@CliOpts{repor | ||||
|             <+> str "/" | ||||
|             <+> total | ||||
|             <+> str ")" | ||||
|     cleared = if (cleared_ $ reportopts_ $ cliopts_ uopts) | ||||
|               then withAttr (borderAttr <> "query") (str " cleared") | ||||
|               else str "" | ||||
|     togglefilters = | ||||
|       case concat [ | ||||
|            if cleared_ ropts then ["cleared"] else [] | ||||
|           ,if real_ ropts then ["real"] else [] | ||||
|           ] of | ||||
|         [] -> str "" | ||||
|         fs -> withAttr (borderAttr <> "query") (str $ " " ++ intercalate ", " fs) | ||||
|     cur = str $ case l^.listSelectedL of | ||||
|                  Nothing -> "-" | ||||
|                  Just i -> show (i + 1) | ||||
| @ -158,6 +162,7 @@ drawRegisterScreen AppState{aopts=uopts -- @UIOpts{cliopts_=_copts@CliOpts{repor | ||||
|            -- ("up/down/pgup/pgdown/home/end", "move") | ||||
|            ("left", "back") | ||||
|           ,("C", "cleared?") | ||||
|           ,("R", "real?") | ||||
|           ,("right/enter", "transaction") | ||||
|           ,("g", "reload") | ||||
|           ,("q", "quit") | ||||
| @ -206,6 +211,7 @@ handleRegisterScreen st@AppState{ | ||||
|         Left err -> continue $ screenEnter d ES.screen{esState=err} st | ||||
| 
 | ||||
|     Vty.EvKey (Vty.KChar 'C') [] -> continue $ reload j d $ stToggleCleared st | ||||
|     Vty.EvKey (Vty.KChar 'R') [] -> continue $ reload j d $ stToggleReal st | ||||
| 
 | ||||
|     Vty.EvKey (Vty.KLeft) []     -> continue $ popScreen st | ||||
| 
 | ||||
|  | ||||
| @ -9,7 +9,7 @@ where | ||||
| 
 | ||||
| -- import Lens.Micro ((^.)) | ||||
| import Control.Monad.IO.Class (liftIO) | ||||
| -- import Data.List | ||||
| import Data.List | ||||
| -- import Data.List.Split (splitOn) | ||||
| -- import Data.Ord | ||||
| import Data.Monoid | ||||
| @ -22,7 +22,7 @@ import Graphics.Vty as Vty | ||||
| -- import Safe (headDef, lastDef) | ||||
| import Brick | ||||
| import Brick.Widgets.List (listMoveTo) | ||||
| -- import Brick.Widgets.Border | ||||
| import Brick.Widgets.Border (borderAttr) | ||||
| -- import Brick.Widgets.Border.Style | ||||
| -- import Brick.Widgets.Center | ||||
| -- import Text.Printf | ||||
| @ -43,12 +43,22 @@ screen = TransactionScreen{ | ||||
|   } | ||||
| 
 | ||||
| initTransactionScreen :: Day -> AppState -> AppState | ||||
| initTransactionScreen _d st@AppState{aopts=_opts, ajournal=_j, aScreen=_s@TransactionScreen{tsState=_}} = st | ||||
| initTransactionScreen d st@AppState{aopts=UIOpts{cliopts_=CliOpts{reportopts_=ropts}} | ||||
|                                     ,ajournal=_j | ||||
|                                     ,aScreen=s@TransactionScreen{tsState=((n,t),nts,a)}} = | ||||
|   st{aScreen=s{tsState=((n, t'),nts,a)}} | ||||
|   where | ||||
|     -- re-filter the postings, eg because real/virtual was toggled. | ||||
|     -- get the original transaction from the list passed from the register screen. | ||||
|     t' = case lookup n nts of | ||||
|       Just torig -> filterTransactionPostings (queryFromOpts d ropts) torig | ||||
|       Nothing    -> t -- shouldn't happen | ||||
| 
 | ||||
| initTransactionScreen _ _ = error "init function called with wrong screen type, should not happen" | ||||
| 
 | ||||
| drawTransactionScreen :: AppState -> [Widget] | ||||
| drawTransactionScreen AppState{ -- aopts=_uopts@UIOpts{cliopts_=_copts@CliOpts{reportopts_=_ropts@ReportOpts{query_=querystr}}}, | ||||
|                                aScreen=TransactionScreen{tsState=((i,t),nts,acct)}} = [ui] | ||||
| drawTransactionScreen AppState{aopts=UIOpts{cliopts_=CliOpts{reportopts_=ropts}} | ||||
|                               ,aScreen=TransactionScreen{tsState=((i,t),nts,acct)}} = [ui] | ||||
|   where | ||||
|     -- datedesc = show (tdate t) ++ " " ++ tdescription t | ||||
|     toplabel = | ||||
| @ -59,9 +69,18 @@ drawTransactionScreen AppState{ -- aopts=_uopts@UIOpts{cliopts_=_copts@CliOpts{r | ||||
|       <+> str " (" | ||||
|       <+> withAttr ("border" <> "bold") (str $ show i) | ||||
|       <+> str (" of "++show (length nts)++" in "++T.unpack acct++")") | ||||
|       <+> togglefilters | ||||
|     togglefilters = | ||||
|       case concat [ | ||||
|            if cleared_ ropts then ["cleared"] else [] | ||||
|           ,if real_ ropts then ["real"] else [] | ||||
|           ] of | ||||
|         [] -> str "" | ||||
|         fs -> withAttr (borderAttr <> "query") (str $ " " ++ intercalate ", " fs) <+> str " postings" | ||||
|     bottomlabel = borderKeysStr [ | ||||
|        ("left", "back") | ||||
|       ,("up/down", "prev/next") | ||||
|       ,("R", "real?") | ||||
|       ,("g", "reload") | ||||
|       ,("q", "quit") | ||||
|       ] | ||||
| @ -114,6 +133,10 @@ handleTransactionScreen st@AppState{ | ||||
| 
 | ||||
|     -- Vty.EvKey (Vty.KChar 'C') [] -> continue $ reload j d $ stToggleCleared st | ||||
| 
 | ||||
|     Vty.EvKey (Vty.KChar 'R') [] -> | ||||
|       -- just show/hide the real postings in this transaction, don't bother updating parent screens | ||||
|       continue $ reload j d $ stToggleReal st | ||||
| 
 | ||||
|     Vty.EvKey (Vty.KUp) []       -> continue $ reload j d st{aScreen=s{tsState=((iprev,tprev),nts,acct)}} | ||||
|     Vty.EvKey (Vty.KDown) []     -> continue $ reload j d st{aScreen=s{tsState=((inext,tnext),nts,acct)}} | ||||
| 
 | ||||
|  | ||||
| @ -16,6 +16,8 @@ module Hledger.UI.UIUtils ( | ||||
|  ,borderKeysStr | ||||
|  -- | ||||
|  ,stToggleCleared | ||||
|  ,stToggleFlat | ||||
|  ,stToggleReal | ||||
|  ) where | ||||
| 
 | ||||
| import Lens.Micro ((^.)) | ||||
| @ -47,6 +49,23 @@ stToggleCleared st@AppState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts | ||||
| toggleCleared :: ReportOpts -> ReportOpts | ||||
| toggleCleared ropts = ropts{cleared_=not $ cleared_ ropts} | ||||
| 
 | ||||
| stToggleFlat :: AppState -> AppState | ||||
| stToggleFlat st@AppState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} = | ||||
|   st{aopts=uopts{cliopts_=copts{reportopts_=toggleFlatMode ropts}}} | ||||
| 
 | ||||
| -- | Toggle between flat and tree mode. If in the third "default" mode, go to flat mode. | ||||
| toggleFlatMode :: ReportOpts -> ReportOpts | ||||
| toggleFlatMode ropts@ReportOpts{accountlistmode_=ALFlat} = ropts{accountlistmode_=ALTree} | ||||
| toggleFlatMode ropts = ropts{accountlistmode_=ALFlat} | ||||
| 
 | ||||
| stToggleReal :: AppState -> AppState | ||||
| stToggleReal st@AppState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} = | ||||
|   st{aopts=uopts{cliopts_=copts{reportopts_=toggleReal ropts}}} | ||||
| 
 | ||||
| -- | Toggle between showing all and showing only real (non-virtual) items. | ||||
| toggleReal :: ReportOpts -> ReportOpts | ||||
| toggleReal ropts = ropts{real_=not $ real_ ropts} | ||||
| 
 | ||||
| -- | Regenerate the content for the current and previous screens, from a new journal and current date. | ||||
| reload :: Journal -> Day -> AppState -> AppState | ||||
| reload j d st@AppState{aScreen=s,aPrevScreens=ss} = | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user