emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/dicom 3b56c4d0e8 1/5: Bookmark support and many improve


From: ELPA Syncer
Subject: [elpa] externals/dicom 3b56c4d0e8 1/5: Bookmark support and many improvements
Date: Fri, 20 Dec 2024 15:58:02 -0500 (EST)

branch: externals/dicom
commit 3b56c4d0e85cd5451662fd899e2138ded6df60fa
Author: Daniel Mendler <mail@daniel-mendler.de>
Commit: Daniel Mendler <mail@daniel-mendler.de>

    Bookmark support and many improvements
---
 dicom.el | 253 +++++++++++++++++++++++++++++++--------------------------------
 1 file changed, 125 insertions(+), 128 deletions(-)

diff --git a/dicom.el b/dicom.el
index 6b4f5d3293..72338b9a62 100644
--- a/dicom.el
+++ b/dicom.el
@@ -78,16 +78,16 @@
 (defvar-local dicom--proc nil
   "Active conversion process in current buffer.")
 
-(defconst dicom--dir-placeholder
+(defconst dicom--thumb-placeholder
   '( :margin 8 :type svg :width 267 :height 200
      :data "<svg xmlns='http://www.w3.org/2000/svg' width='267' height='200'>
   <rect width='267' height='200' fill='black' stroke='gray' stroke-width='1'/>
   <line x1='0' y1='0' x2='267' y2='200' stroke='gray' stroke-width='1'/>
   <line x1='0' y1='200' x2='267' y2='0' stroke='gray' stroke-width='1'/>
 </svg>")
-  "Placeholder image in `dicom-dir-mode' buffers.")
+  "Thumbnail placeholder image.")
 
-(defconst dicom--image-placeholder
+(defconst dicom--large-placeholder
   (propertize
    " "
    'pointer 'arrow
@@ -98,17 +98,19 @@
   <line x1='0' y1='0' x2='800' y2='600' stroke='gray' stroke-width='1'/>
   <line x1='0' y1='600' x2='800' y2='0' stroke='gray' stroke-width='1'/>
 </svg>"))
-  "Placeholder image in `dicom-image-mode' buffers.")
+  "Large placeholder image.")
 
 (defun dicom--stop (proc)
   "Gracefully stop PROC."
-  (ignore-errors (signal-process proc 'TERM))
-  (run-at-time 1 nil (lambda () (ignore-errors (delete-process proc)))))
+  (when proc
+    (ignore-errors (signal-process proc 'TERM))
+    (run-at-time 1 nil (lambda () (ignore-errors (delete-process proc))))))
 
 (defun dicom--put-image (pos file)
   "Display image FILE at POS."
   (with-silent-modifications
-    (put-text-property pos (1+ pos) 'display `(image :margin 8 :type png :file 
,file))))
+    (put-text-property pos (1+ pos) 'display
+                       `(image :margin 8 :type png :file ,file))))
 
 (defun dicom--async (cb &rest args)
   "Run process with ARGS asynchronously and call CB when the process finished."
@@ -187,7 +189,7 @@
                 (mouse-posn-property (event-start last-input-event)
                                      'dicom--file)
               (get-text-property (point) 'dicom--file))))
-      (dicom-open file 'reuse)
+      (dicom-open file (and (not last-prefix-arg) "*dicom image*"))
     (user-error "No image at point")))
 
 (defvar-keymap dicom-dir-mode-map
@@ -214,27 +216,20 @@
 
 (defun dicom-open (file &optional reuse)
   "Open DICOM dir or image FILE.
-If REUSE is non-nil, reuse image buffer."
+REUSE can be a buffer name to reuse."
   (interactive "fDICOM: ")
-  (if (or (file-directory-p file) (string-suffix-p "/DICOMDIR" file))
-      (let* ((default-directory
-              (file-name-as-directory
-               (expand-file-name (string-remove-suffix "/DICOMDIR" file))))
-             (buf (dicom--buffer-name default-directory)))
-        (unless (get-buffer buf)
-          (with-current-buffer (get-buffer-create buf)
-            (dicom--dir-setup)))
-        (pop-to-buffer buf))
-    (let* ((file (expand-file-name file))
-           (default-directory (file-name-directory file))
-           (buf (if reuse "*dicom image*" (dicom--buffer-name file))))
-      (unless (when-let ((buf (get-buffer buf)))
-                (equal (buffer-local-value 'dicom--file buf) file))
-        (with-current-buffer (get-buffer-create buf)
-          (dicom--image-setup file)))
-      (if reuse
-          (display-buffer buf)
-        (pop-to-buffer buf)))))
+  (let* ((file (expand-file-name (if (directory-name-p file)
+                                     (file-name-concat file "DICOMDIR")
+                                   file)))
+         (default-directory (file-name-directory file))
+         (buf (or reuse (dicom--buffer-name file))))
+    (unless (when-let ((buf (get-buffer buf)))
+              (equal (buffer-local-value 'dicom--file buf) file))
+      (with-current-buffer (get-buffer-create buf)
+        (dicom--setup file)))
+    (if reuse
+        (display-buffer buf)
+      (pop-to-buffer buf))))
 
 (defun dicom--process-queue ()
   "Process conversion queue."
@@ -251,25 +246,16 @@ If REUSE is non-nil, reuse image buffer."
                      (dicom--process-queue))
                    "convert" src "-delete" "1--1" "-thumbnail" "x200" tmp))))
 
-(defun dicom--setup-outline ()
-  "Setup outline mode."
-  (goto-char (point-min))
-  (setq-local outline-regexp " [A-Z]"
-              outline-minor-mode-cycle t
-              outline-minor-mode-use-buttons 'in-margins)
-  (outline-minor-mode))
-
 (defun dicom--play (rate)
   "Play DICOM multi frame image with frame RATE."
   (pcase-let ((`(,dst . ,tmp) (dicom--cache-name dicom--file "mp4")))
     (cond
      ((file-exists-p dst)
       (message "Playing %s…" dicom--file)
-      (unless (eq 0 (call-process-shell-command
-                     (format "(mpv --loop %s) & disown"
-                             (shell-quote-argument dst))
-                     nil 0))
-        (error "Could not play video with mpv")))
+      (call-process-shell-command
+       (format "(mpv --loop %s) & disown"
+               (shell-quote-argument dst))
+       nil 0))
      (dicom--proc
       (message "Conversion in progress…"))
      (t
@@ -287,116 +273,127 @@ If REUSE is non-nil, reuse image buffer."
                               rate
                               (shell-quote-argument tmp))))))))
 
-(defun dicom--image-setup (file)
-  "Setup `dicom-image-mode' buffer for image FILE."
-  (dicom-image-mode)
-  (dicom--stop dicom--proc)
-  (setq-local dicom--proc nil
-              dicom--file file
-              buffer-read-only t
-              revert-buffer-function (lambda (&rest _) (dicom--image-setup 
file))
-              header-line-format
-              (format
-               (propertize " DICOM IMAGE %s"
-                           'face '(:inherit header-line :height 1.5 :weight 
bold))
-               (if-let ((dir (locate-dominating-file file "DICOMDIR")))
-                   (file-name-sans-extension
-                    (file-relative-name file (file-name-parent-directory dir)))
-                 (file-name-base file))))
-  (with-silent-modifications
-    (erase-buffer)
-    (insert "\n")
-    (pcase-let* ((default-directory "/")
-                 (`(,dst . ,tmp) (dicom--cache-name (concat "large" file)))
-                 (pos (point))
-                 (data (dicom--read dicom--file)))
-      (insert dicom--image-placeholder "\n")
-      (when (alist-get 'NumberOfFrames (car data))
-        (insert-button
-         "[PLAY]" 'action
-         (lambda (_)
-           (dicom--play (or (alist-get 'RecommendedDisplayFrameRate (car data))
-                            (alist-get 'CineRate (car data))
-                            25))))
-        (insert "\n"))
-      (mapc #'dicom--insert data)
-      (dicom--setup-outline)
-      (if (file-exists-p dst)
-          (dicom--put-image pos dst)
-        (dicom--async (lambda (success)
-                        (if success
-                         (progn
-                           (rename-file tmp dst)
-                           (dicom--put-image pos dst))
-                       (delete-file tmp)))
-                      "convert" file "-delete" "1--1" tmp)))))
-
-(defun dicom--dir-setup ()
-  "Setup `dicom-dir-mode' buffer."
-  (dicom-dir-mode)
+(defun dicom--setup (file)
+  "Setup buffer for FILE."
   (dicom--stop dicom--proc)
+  (if (string-suffix-p "DICOMDIR" file) (dicom-dir-mode) (dicom-image-mode))
   (setq-local dicom--queue nil
               dicom--proc nil
-              dicom--file (expand-file-name "DICOMDIR")
+              dicom--file file
               buffer-read-only t
               truncate-lines nil
-              revert-buffer-function (lambda (&rest _) (dicom--dir-setup))
+              bookmark-make-record-function #'dicom--bookmark-record
+              revert-buffer-function (lambda (&rest _) (dicom--setup file))
               fringe-indicator-alist '((continuation . nil)
                                        (truncation . nil))
+              outline-regexp " [A-Z]"
+              outline-minor-mode-cycle t
+              outline-minor-mode-use-buttons 'in-margins
               header-line-format
-              (format (propertize " DICOM DIR %s"
-                                  'face '(:inherit header-line :height 1.5 
:weight bold))
-                      (file-name-base (directory-file-name 
default-directory))))
+              (format (propertize
+                       " %s %s"
+                       'face '(:inherit header-line :height 1.5 :weight bold))
+                      mode-name (cadr (dicom--shorten dicom--file))))
   (with-silent-modifications
     (erase-buffer)
-    (dolist (item (dicom--read dicom--file))
-      (let ((type (alist-get 'DirectoryRecordType item))
-            (pos (point)))
-        (dicom--insert item)
-        (when (equal type "IMAGE")
-          (pcase-let* ((src (expand-file-name
-                             (string-replace "\\" "/" (alist-get 
'ReferencedFileID item))))
-                       (`(,dst . ,tmp) (dicom--cache-name src))
-                       (tooltip (buffer-substring-no-properties (1+ pos) 
(point))))
-            (delete-region pos (point))
-            (insert (propertize
-                     " " 'display `(image ,@dicom--dir-placeholder)
-                     'pointer 'arrow
-                     'dicom--file src
-                     'help-echo tooltip))
-            (if (file-exists-p dst)
-                (dicom--put-image pos dst)
-              (push (list pos dst tmp src) dicom--queue))))))
-    (dicom--setup-outline)
-    (setq dicom--queue (nreverse dicom--queue))
-    (dicom--process-queue)))
+    (funcall (intern (format "%s--setup" major-mode)))
+    (goto-char (point-min))
+    (outline-minor-mode)))
+
+(defun dicom-image-mode--setup ()
+  "Setup `dicom-image-mode' buffer."
+  (insert "\n")
+  (pcase-let* ((`(,dst . ,tmp) (dicom--cache-name (concat "large" 
dicom--file)))
+               (pos (point))
+               (data (dicom--read dicom--file)))
+    (insert dicom--large-placeholder "\n")
+    (when-let ((frames (alist-get 'NumberOfFrames (car data))))
+      (insert-button
+       (format "[PLAY %s FRAMES]" frames)
+       'action
+       (lambda (_)
+         (dicom--play (or (alist-get 'RecommendedDisplayFrameRate (car data))
+                          (alist-get 'CineRate (car data))
+                          25))))
+      (insert "\n"))
+    (mapc #'dicom--insert data)
+    (if (file-exists-p dst)
+        (dicom--put-image pos dst)
+      (dicom--async (lambda (success)
+                      (if success
+                          (progn
+                            (rename-file tmp dst)
+                            (dicom--put-image pos dst))
+                        (delete-file tmp)))
+                    "convert" dicom--file "-delete" "1--1" tmp))))
+
+(defun dicom-dir-mode--setup ()
+  "Setup `dicom-dir-mode' buffer."
+  (dolist (item (dicom--read dicom--file))
+    (let ((type (alist-get 'DirectoryRecordType item))
+          (pos (point)))
+      (dicom--insert item)
+      (when (equal type "IMAGE")
+        (pcase-let* ((src (expand-file-name
+                           (string-replace "\\" "/" (alist-get 
'ReferencedFileID item))))
+                     (`(,dst . ,tmp) (dicom--cache-name src))
+                     (tooltip (buffer-substring-no-properties (1+ pos) 
(point))))
+          (delete-region pos (point))
+          (insert (propertize
+                   " " 'display `(image ,@dicom--thumb-placeholder)
+                   'pointer 'arrow
+                   'dicom--file src
+                   'help-echo tooltip))
+          (if (file-exists-p dst)
+              (dicom--put-image pos dst)
+            (push (list pos dst tmp src) dicom--queue))))))
+  (setq dicom--queue (nreverse dicom--queue))
+  (dicom--process-queue))
+
+(defun dicom--shorten (file)
+  "Shortened FILE name."
+  (if (string-suffix-p "DICOMDIR" file)
+      (list "dicom dir: "
+            (file-name-base
+             (directory-file-name
+              (file-name-parent-directory file))))
+    (list "dicom image: "
+          (if-let ((dir (locate-dominating-file file "DICOMDIR")))
+              (file-name-sans-extension
+               (file-relative-name file (file-name-parent-directory dir)))
+            (file-name-base file)))))
 
 (defun dicom--buffer-name (file)
   "Buffer name for FILE."
-  (format "*dicom: %s*" (file-name-base (directory-file-name file))))
-
-;;;###autoload
-(defun dicom-dir-mode-auto ()
-  "Enable `dicom-dir-mode' in current buffer."
-  (setq-local buffer-file-name nil
-              buffer-file-truename nil)
-  (rename-buffer (dicom--buffer-name default-directory) t)
-  (dicom--dir-setup))
+  (format "*%s*" (string-join (dicom--shorten file))))
 
 ;;;###autoload
-(defun dicom-image-mode-auto ()
-  "Enable `dicom-image-mode' in current buffer."
+(defun dicom-auto-mode ()
+  "Enable either `dicom-image-mode' or `dicom-dir-mode' in current buffer."
   (let ((file (expand-file-name buffer-file-name)))
     (setq-local buffer-file-name nil
                 buffer-file-truename nil)
     (rename-buffer (dicom--buffer-name file) t)
-    (dicom--image-setup file)))
+    (dicom--setup file)))
+
+;;;###autoload
+(add-to-list 'auto-mode-alist '("\\.\\(?:dcm\\|ima\\)\\'" . dicom-auto-mode))
 
 ;;;###autoload
-(add-to-list 'auto-mode-alist '("\\.\\(?:dcm\\|ima\\)\\'" . 
dicom-image-mode-auto))
+(add-to-list 'auto-mode-alist '("DICOMDIR\\'" . dicom-auto-mode))
 
 ;;;###autoload
-(add-to-list 'auto-mode-alist '("DICOMDIR\\'" . dicom-dir-mode-auto))
+(defun dicom-bookmark-jump (bm)
+  "Jump to DICOM bookmark BM."
+  (declare-function bookmark-get-filename "bookmark")
+  (dicom-open (bookmark-get-filename bm)))
+(put 'dicom-bookmark-jump 'bookmark-handler-type "DICOM")
+
+(defun dicom--bookmark-record ()
+  "Create DICOM bookmark."
+  `(,(string-join (dicom--shorten dicom--file))
+    (filename . ,dicom--file)
+    (handler . ,#'dicom-bookmark-jump)))
 
 (provide 'dicom)
 ;;; dicom.el ends here



reply via email to

[Prev in Thread] Current Thread [Next in Thread]