; This program is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 2 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
; This script will present a dialog that allows the user to queue up
; a bunch of files for later, one-at-a-time processing.
;
; The script adds a new submenu, "File->Sequential Edit" containing
; three new commands.
; "Choose Files..." presents a dialog which permits selecting the files
; that are to be queued up for editing. There are two components to this
; dialog. First, the user is able to select a base directory which contains
; the files, while the second is a list of filenames to be added to the
; queue. Wildcard patterns can be specified to match multiple files (e.g.,
; *.jpg). The filename patterns should be separated by spaces, and
; any filename containing spaces should be place within double quotes.
; If an absolute path is provided, the base directory specified is ignored
; for that particular pattern.
; The "Save and open next" command will result in the file being saved
; back to the original location, overwriting the original file. The image
; is then close and the next one in the queue opened.
; Note: if there is no image open when "Save and open next" is performed,
; or the current image was not one that was queued up, then
; "Save and open next" will merely open the next file in the
; queue. This allows one to abandon edits in the current file
; and yet continue editing the remaining queued files.
(define (script-fu-sg-sequential-open dir pattern-string)
(define (remove lis item)
(let loop ((lis lis)
(result '()) )
(if (null? lis)
(reverse result)
(loop (cdr lis)
(if (equal? (car lis) item)
result
(cons (car lis) result) )))))
(define (set-prefix s dir)
(if (equal? (make-string 1 (string-ref s 0)) DIR-SEPARATOR)
s
(string-append dir DIR-SEPARATOR s) ))
;; Starting with the second pattern, every other pattern
;; is a glob enclosed in quotes (most likely containing spaces).
(let ((patterns
(let loop ((patterns (strbreakup pattern-string "\""))
(unquoteds '())
(quoteds '())
(no-quote #t) )
(if (null? patterns)
(append unquoteds quoteds)
(loop (cdr patterns)
(if no-quote
(append unquoteds (remove (strbreakup (car patterns) " ") ""))
unquoteds )
(if no-quote
quoteds
(append quoteds (list (car patterns))) )
(not no-quote) )))))
(let ((files (let loop ((patterns (if (pair? patterns)
(map (lambda (x) (set-prefix x dir))
patterns )
'() ))
(filenames '()) )
(if (null? patterns)
filenames
(loop (cdr patterns)
(append filenames (cadr (file-glob (car patterns) 1))) )))))
(gimp-parasite-detach "sequential-queue")
(gimp-parasite-detach "sequential-display")
(unless (null? files)
(gimp-parasite-attach (list "sequential-queue"
2
(unbreakupstr (cdr files) ":") ))
(let ((image (catch #f (car (gimp-file-load RUN-NONINTERACTIVE
(car files)
(car files) )))))
(if image
(gimp-parasite-attach
(list "sequential-display"
2
(string-append (number->string (car (gimp-display-new image)))
":"
(car files) )))))))
(gimp-progress-end) ))
(define (script-fu-sg-save-and-next)
(define (find-opened-image filename)
(let loop ((images (vector->list (cadr (gimp-image-list))))
(image-id #f) )
(if (null? images)
image-id
(loop (cdr images)
(or image-id
(if (string=? filename
(car (gimp-image-get-filename (car images))) )
(car images)
#f ))))))
(let* ((prev-filename (catch #f
(cadr (strbreakup (caddar (gimp-parasite-find
"sequential-display" ))
":" ))))
(prev-view
(catch #f (string->number
(car (strbreakup
(caddar (gimp-parasite-find "sequential-display"))
":" )))))
(image (if prev-filename
(find-opened-image prev-filename)
#f ))
(saved? #f) )
(catch #f (gimp-parasite-detach "sequential-display"))
(when image
(let ((ext (car (last (strbreakup prev-filename "."))))
(layer #f) )
(if (or (string-ci=? ext "gz")
(string-ci=? ext "bz2")
(string-ci=? ext "xcf")
(string-ci=? ext "xcfgz")
(string-ci=? ext "xcfbz2") )
(set! layer (car (gimp-image-get-active-layer image)))
(set! layer (car (gimp-image-merge-visible-layers image CLIP-TO-IMAGE))) )
(set! saved? (catch #f (car (gimp-file-save RUN-NONINTERACTIVE
image
layer
prev-filename
prev-filename ))))))
(let ((queue (catch #f (caddar (gimp-parasite-find "sequential-queue")))))
(if queue
(let ((files (strbreakup queue ":")))
(gimp-parasite-detach "sequential-queue")
(unless (null? (cdr files))
(gimp-parasite-attach (list "sequential-queue"
2
(unbreakupstr (cdr files) ":") )))
(let ((new-image (catch #f (car (gimp-file-load RUN-NONINTERACTIVE
(car files)
(car files) )))))
(if (and image prev-view)
(begin
(gimp-displays-reconnect image new-image)
(gimp-parasite-attach
(list "sequential-display"
2
(string-append (number->string prev-view)
":"
(car files) ))))
(begin
(gimp-parasite-attach
(list "sequential-display"
2
(string-append (number->string (car (gimp-display-new new-image)))
":"
(car files) )))))))))
(unless saved?
(gimp-message "Failed to save file") )
(unless image
(gimp-message "No image available for sequential edit") ))
(gimp-displays-flush)
(gimp-progress-end) )
(script-fu-register "script-fu-sg-sequential-open"
"Choose Files..."
"Open a set of files to edit one-at-a-time"
"Saul Goode"
"Saul Goode"
"March 2014"
""
SF-DIRNAME "Directory" "."
SF-STRING "Pattern" "*.jpg"
)
(script-fu-menu-register "script-fu-sg-sequential-open"
"<Image>/File/Sequential Edit"
)
(script-fu-register "script-fu-sg-save-and-next"
"Save and Open Next"
"Save current file, close it, and open next file in queue"
"Saul Goode"
"Saul Goode"
"March 2014"
""
)
(script-fu-menu-register "script-fu-sg-save-and-next"
"<Image>/File/Sequential Edit"
)