Implemented showing a clock report in the agenda.

This is a new display mode in the agenda view.  It appends a clock
table to the daily/weekly agenda view that covers clocked time
for the time span shown in the agenda, and also limited to the
files that were used to create the current view.
This commit is contained in:
Carsten Dominik 2008-04-04 23:44:48 +02:00
parent f87667c730
commit 3ab4658e17
8 changed files with 121 additions and 9 deletions

2
.gitignore vendored
View File

@ -42,6 +42,8 @@ tmp
*~
.DS_Store
*#
.#*
#
# Local variables:

View File

@ -1,5 +1,19 @@
2008-04-06 Carsten Dominik <dominik@science.uva.nl>
* lisp/org-agenda.el (org-agenda-start-with-clockreport-mode): New
option.
* lisp/org-clock.el (org-dblock-write:clocktable): Request the
unrestricted list of files.
(org-get-clocktable): New function.
(org-dblock-write:clocktable): Make sure :tstart and :tend can not
only be strings but also integers (an absolute day number) and
lists (m d y).
2008-04-04 Carsten Dominik <dominik@science.uva.nl>
* lisp/org-agenda.el (org-agenda-clocktable-mode): New variable.
* doc/org.texi (Agenda commands): Document columns view in the
agenda.

View File

@ -53,6 +53,14 @@
total time for each file will now also be listed. This was
a request from Bernt Hansen.
*** Clockreport in the daily/weekly arenda
If you turn on clockreport mode with the "R" key in the
agenda, a clock table will be attached to the agenda, showing
the clock report for the file scope and time interval of the
agenda view. To turn this on permanently, configure the
variable =org-agenda-start-with-clockreport-mode=.
*** Selective tag inheritance
Inheritance of tags can now be limited to a subset of all

View File

@ -5477,6 +5477,14 @@ previously used indirect buffer.
Toggle Logbook mode. In Logbook mode, entries that where marked DONE while
logging was on (variable @code{org-log-done}) are shown in the agenda,
as are entries that have been clocked on that day.
@c
@kindex R
@item R
Toggle Clockreport mode. In clockreport mode, the daily/weekly agenda will
always show a table with the clocked times for the timespan and file scope
covered by the current agenda view. The initial setting for this mode in new
agenda buffers can be set with the variable
@code{org-agenda-start-with-follow-mode}.
@tsubheading{Change display}
@cindex display changing, in agenda

View File

@ -486,6 +486,11 @@ Needs to be set before org.el is loaded."
:group 'org-agenda-startup
:type 'boolean)
(defcustom org-agenda-start-with-clockreport-mode nil
"The initial value of clockreport-mode in a newly created agenda window."
:group 'org-agenda-startup
:type 'boolean)
(defgroup org-agenda-windows nil
"Options concerning the windows used by the Agenda in Org Mode."
:tag "Org Agenda Windows"
@ -922,6 +927,7 @@ works you probably want to add it to `org-agenda-custom-commands' for good."
(defvar org-agenda-menu) ; defined later in this file.
(defvar org-agenda-follow-mode nil)
(defvar org-agenda-clockreport-mode nil)
(defvar org-agenda-show-log nil)
(defvar org-agenda-redo-command nil)
(defvar org-agenda-query-string nil)
@ -956,6 +962,7 @@ The following commands are available:
buffer-substring-filters)))
(unless org-agenda-keep-modes
(setq org-agenda-follow-mode org-agenda-start-with-follow-mode
org-agenda-clockreport-mode org-agenda-start-with-clockreport-mode
org-agenda-show-log nil))
(easy-menu-change
'("Agenda") "Agenda Files"
@ -1016,6 +1023,7 @@ The following commands are available:
(int-to-string (pop l)) 'digit-argument)))
(org-defkey org-agenda-mode-map "f" 'org-agenda-follow-mode)
(org-defkey org-agenda-mode-map "R" 'org-agenda-clockreport-mode)
(org-defkey org-agenda-mode-map "l" 'org-agenda-log-mode)
(org-defkey org-agenda-mode-map "D" 'org-agenda-toggle-diary)
(org-defkey org-agenda-mode-map "G" 'org-agenda-toggle-time-grid)
@ -1140,6 +1148,8 @@ The following commands are available:
"--"
["Show Logbook entries" org-agenda-log-mode
:style toggle :selected org-agenda-show-log :active (org-agenda-check-type nil 'agenda 'timeline)]
["Show clock report" org-agenda-clockreport-mode
:style toggle :selected org-agenda-clockreport-mode :active (org-agenda-check-type nil 'agenda)]
["Include Diary" org-agenda-toggle-diary
:style toggle :selected org-agenda-include-diary :active (org-agenda-check-type nil 'agenda)]
["Use Time Grid" org-agenda-toggle-time-grid
@ -2161,7 +2171,8 @@ given in `org-agenda-start-on-weekday'."
(day-numbers (list start))
(day-cnt 0)
(inhibit-redisplay (not debug-on-error))
s e rtn rtnall file date d start-pos end-pos todayp nd)
s e rtn rtnall file date d start-pos end-pos todayp nd
clocktable-start clocktable-end)
(setq org-agenda-redo-command
(list 'org-agenda-list (list 'quote include-all) start-day ndays))
;; Make the list of days
@ -2171,6 +2182,8 @@ given in `org-agenda-start-on-weekday'."
(push (1+ (car day-numbers)) day-numbers)
(setq ndays (1- ndays)))
(setq day-numbers (nreverse day-numbers))
(setq clocktable-start (car day-numbers)
clocktable-end (1+ (or (org-last day-numbers) 0)))
(org-prepare-agenda "Day/Week")
(org-set-local 'org-starting-day (car day-numbers))
(org-set-local 'org-include-all-loc include-all)
@ -2254,6 +2267,11 @@ given in `org-agenda-start-on-weekday'."
"\n"))
(put-text-property s (1- (point)) 'day d)
(put-text-property s (1- (point)) 'org-day-cnt day-cnt))))
(when (and org-agenda-clockreport-mode clocktable-start)
(let ((org-agenda-files (org-agenda-files)))
;; the above line is to ensure the restricted range!
(insert (org-get-clocktable :tstart clocktable-start
:tend clocktable-end :link t))))
(goto-char (point-min))
(org-fit-agenda-window)
(unless (and (pos-visible-in-window-p (point-min))
@ -4102,6 +4120,16 @@ so that the date SD will be in that range."
(message "Follow mode is %s"
(if org-agenda-follow-mode "on" "off")))
(defun org-agenda-clockreport-mode ()
"Toggle clocktable mode in an agenda buffer."
(interactive)
(org-agenda-check-type t 'agenda)
(setq org-agenda-clockreport-mode (not org-agenda-clockreport-mode))
(org-agenda-set-mode-name)
(org-agenda-redo)
(message "Clocktable mode is %s"
(if org-agenda-clockreport-mode "on" "off")))
(defun org-agenda-log-mode ()
"Toggle log mode in an agenda buffer."
(interactive)
@ -4141,7 +4169,8 @@ so that the date SD will be in that range."
(if org-agenda-follow-mode " Follow" "")
(if org-agenda-include-diary " Diary" "")
(if org-agenda-use-time-grid " Grid" "")
(if org-agenda-show-log " Log" "")))
(if org-agenda-show-log " Log" "")
(if org-agenda-clockreport-mode " Clock" "")))
(force-mode-line-update))
(defun org-agenda-post-command-hook ()

View File

@ -395,6 +395,29 @@ and is only done if the variable `org-clock-out-when-done' is not nil."
(add-hook 'org-after-todo-state-change-hook
'org-clock-out-if-current)
;;;###autoload
(defun org-get-clocktable (&rest props)
"Get a formatted clocktable with parameters according to PROPS.
The table is created in a temporary buffer, fully formatted and
fontified, and then returned."
;; Set the defaults
(setq props (plist-put props :name "clocktable"))
(unless (plist-member props :maxlevel)
(setq props (plist-put props :maxlevel 2)))
(unless (plist-member props :link)
(setq props (plist-put props :link nil)))
(unless (plist-member props :scope)
(setq props (plist-put props :scope 'agenda)))
(with-temp-buffer
(org-mode)
(org-create-dblock props)
(org-update-dblock)
(font-lock-fontify-buffer)
(forward-line 2)
(buffer-substring (point) (progn
(re-search-forward "^#\\+END" nil t)
(point-at-bol)))))
(defun org-clock-report (&optional arg)
"Create a table containing a report about clocked time.
If the cursor is inside an existing clocktable block, then the table
@ -557,7 +580,7 @@ the currently selected interval size."
(catch 'exit
(let* ((hlchars '((1 . "*") (2 . "/")))
(ins (make-marker))
(total-time nil)
(total-time 0)
(scope (plist-get params :scope))
(tostring (plist-get params :tostring))
(multifile (plist-get params :multifile))
@ -577,6 +600,13 @@ the currently selected interval size."
(when block
(setq cc (org-clock-special-range block nil t)
ts (car cc) te (nth 1 cc) range-text (nth 2 cc)))
(when (integerp ts) (setq ts (calendar-gregorian-from-absolute ts)))
(when (integerp te) (setq te (calendar-gregorian-from-absolute te)))
(when (and ts (listp ts))
(setq ts (format "%4d-%02d-%02d" (nth 2 ts) (car ts) (nth 1 ts))))
(when (and te (listp te))
(setq te (format "%4d-%02d-%02d" (nth 2 te) (car te) (nth 1 te))))
;; Now the times are strings we can parse.
(if ts (setq ts (time-to-seconds
(apply 'encode-time (org-parse-time-string ts)))))
(if te (setq te (time-to-seconds
@ -604,7 +634,7 @@ the currently selected interval size."
(throw 'exit nil))))
(org-narrow-to-subtree))
((or (listp scope) (eq scope 'agenda))
(let* ((files (if (listp scope) scope (org-agenda-files)))
(let* ((files (if (listp scope) scope (org-agenda-files t)))
(scope 'agenda)
(p1 (copy-sequence params))
file)
@ -677,7 +707,7 @@ the currently selected interval size."
(if (eq scope 'agenda) "|" "")
"|"
"*Total time*| *"
(org-minutes-to-hours total-time)
(org-minutes-to-hours (or total-time 0))
"*|\n|-\n")
(setq tbl (delq nil tbl))
(if (and (stringp (car tbl)) (> (length (car tbl)) 1)

View File

@ -27,12 +27,13 @@
;;
;;; Commentary:
;; This file contains macro definitions, defsubst definitions, and
;; oder stuff needed for compilation and top-level forms in Org-mode.
;; This file contains macro definitions, defsubst definitions, other
;; stuff needed for compilation and top-level forms in Org-mode, as well
;; lots of small functions that are not org-mode specific but simply
;; generally useful stuff.
;;; Code:
(defmacro org-bound-and-true-p (var)
"Return the value of symbol VAR if it is bound, else nil."
`(and (boundp (quote ,var)) ,var))
@ -212,6 +213,16 @@ we turn off invisibility temporarily. Use this in a `let' form."
(goto-char (point-at-bol))
(looking-at re)))
(defun org-plist-delete (plist property)
"Delete PROPERTY from PLIST.
This is in contrast to merely setting it to 0."
(let (p)
(while plist
(if (not (eq property (car plist)))
(setq p (plist-put p (car plist) (nth 1 plist))))
(setq plist (cddr plist)))
p))
(provide 'org-macs)
;;; org-macs.el ends here

View File

@ -2831,7 +2831,8 @@ org-remember-apply-template org-remember org-remember-handler)))
'(org-clock-in org-clock-out org-clock-cancel
org-clock-goto org-clock-sum org-clock-display
org-remove-clock-overlays org-clock-report
org-clocktable-shift org-dblock-write:clocktable)))
org-clocktable-shift org-dblock-write:clocktable
org-get-clocktable)))
(defun org-clock-update-time-maybe ()
"If this is a CLOCK line, update it and return t.
@ -15119,3 +15120,12 @@ Still experimental, may disappear in the future."
;; arch-tag: e77da1a7-acc7-4336-b19e-efa25af3f9fd
;;; org.el ends here
(defun org-plist-delete (plist property)
"Delete PROPERTY from PLIST.
This is in contrast to merely setting it to 0."
(let (p)
(while plist
(if (not (eq property (car plist)))
(setq p (plist-put p (car plist) (nth 1 plist))))
(setq plist (cddr plist)))
p))