Browse Source

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.
Carsten Dominik 13 years ago
parent
commit
3ab4658e17
8 changed files with 121 additions and 9 deletions
  1. 2 0
      .gitignore
  2. 14 0
      ChangeLog
  3. 8 0
      ORGWEBPAGE/Changes.org
  4. 8 0
      doc/org.texi
  5. 31 2
      lisp/org-agenda.el
  6. 33 3
      lisp/org-clock.el
  7. 14 3
      lisp/org-macs.el
  8. 11 1
      lisp/org.el

+ 2 - 0
.gitignore

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

+ 14 - 0
ChangeLog

@@ -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.
 

+ 8 - 0
ORGWEBPAGE/Changes.org

@@ -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

+ 8 - 0
doc/org.texi

@@ -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

+ 31 - 2
lisp/org-agenda.el

@@ -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 ()

+ 33 - 3
lisp/org-clock.el

@@ -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)

+ 14 - 3
lisp/org-macs.el

@@ -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

+ 11 - 1
lisp/org.el

@@ -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))