Batch queue improvements: keyboard shortcuts and a sequence index; on behalf of Adam Reichold (issue 1915)

This commit is contained in:
michael
2013-06-30 08:30:52 -04:00
parent f81c7ccabb
commit 7cb8fc92e4
8 changed files with 70 additions and 9 deletions

View File

@@ -783,7 +783,7 @@ PREFERENCES_MULTITAB;Multiple Editor Tabs Mode
PREFERENCES_OUTDIRFOLDERHINT;Put the saved images to the selected folder PREFERENCES_OUTDIRFOLDERHINT;Put the saved images to the selected folder
PREFERENCES_OUTDIRFOLDER;Save to folder PREFERENCES_OUTDIRFOLDER;Save to folder
PREFERENCES_OUTDIRHINT;You can use the following formatting strings:\n<b>%f</b>, <b>%d1</b>, <b>%d2</b>, ..., <b>%p1</b>, <b>%p2</b>, ..., <b>%r</b>\n\nThese formatting strings refer to the different parts of the photo's pathname or some attributes of the photo.\n\nFor example, if the photo being processed has the following pathname:\n<b><i>/home/tom/photos/2010-10-31/dsc0042.nef</i></b>\nthe meaning of the formatting strings are:\n<b>%d4</b> = <i>home</i>\n<b>%d3</b> = <i>tom</i>\n<b>%d2</b> = <i>photos</i>\n<b>%d1</b> = <i>2010-10-31</i>\n<b>%f</b> = <i>dsc0042</i>\n<b>%p1</b> = <i>/home/tom/photos/2010-10-31/</i>\n<b>%p2</b> = <i>/home/tom/photos/</i>\n<b>%p3</b> = <i>/home/tom/</i>\n<b>%p4</b> = <i>/home/</i>\n\n<b>%r</b> will be replaced by the rank of the photo. If the photo is unranked, %r will be replaced by '0'. If the photo is in the trash bin, %r will be replaced by 'x'.\n\nIf you want to save the output image where the original is, write:\n<b>%p1/%f</b>\n\nIf you want to save the output image in a directory named "<i>converted</i>" located in the directory of the opened image, write:\n<b>%p1/converted/%f</b>\n\nIf you want to save the output image in a directory named "<i>/home/tom/photos/converted/2010-10-31</i>", write:\n<b>%p2/converted/%d1/%f</b> PREFERENCES_OUTDIRHINT;You can use the following formatting strings:\n<b>%f</b>, <b>%d1</b>, <b>%d2</b>, ..., <b>%p1</b>, <b>%p2</b>, ..., <b>%r</b>\n\nThese formatting strings refer to the different parts of the photo's pathname or some attributes of the photo.\n\nFor example, if the photo being processed has the following pathname:\n<b><i>/home/tom/photos/2010-10-31/dsc0042.nef</i></b>\nthe meaning of the formatting strings are:\n<b>%d4</b> = <i>home</i>\n<b>%d3</b> = <i>tom</i>\n<b>%d2</b> = <i>photos</i>\n<b>%d1</b> = <i>2010-10-31</i>\n<b>%f</b> = <i>dsc0042</i>\n<b>%p1</b> = <i>/home/tom/photos/2010-10-31/</i>\n<b>%p2</b> = <i>/home/tom/photos/</i>\n<b>%p3</b> = <i>/home/tom/</i>\n<b>%p4</b> = <i>/home/</i>\n\n<b>%r</b> will be replaced by the rank of the photo. If the photo is unranked, %r will be replaced by '0'. If the photo is in the trash bin, %r will be replaced by 'x'.\n\nIf you want to save the output image where the original is, write:\n<b>%p1/%f</b>\n\nIf you want to save the output image in a directory named "<i>converted</i>" located in the directory of the opened image, write:\n<b>%p1/converted/%f</b>\n\nIf you want to save the output image in a directory named "<i>/home/tom/photos/converted/2010-10-31</i>", write:\n<b>%p2/converted/%d1/%f</b>
PREFERENCES_OUTDIRTEMPLATEHINT;You can use the following formatting strings:\n<b>%f</b>, <b>%d1</b>, <b>%d2</b>, ..., <b>%p1</b>, <b>%p2</b>, ..., <b>%r</b>\n\nThese formatting strings refer to the different parts of the photo's pathname or some attributes of the photo.\n\nFor example, if the photo being processed has the following pathname:\n<b><i>/home/tom/photos/2010-10-31/dsc0042.nef</i></b>\nthe meaning of the formatting strings are:\n<b>%d4</b> = <i>home</i>\n<b>%d3</b> = <i>tom</i>\n<b>%d2</b> = <i>photos</i>\n<b>%d1</b> = <i>2010-10-31</i>\n<b>%f</b> = <i>dsc0042</i>\n<b>%p1</b> = <i>/home/tom/photos/2010-10-31/</i>\n<b>%p2</b> = <i>/home/tom/photos/</i>\n<b>%p3</b> = <i>/home/tom/</i>\n<b>%p4</b> = <i>/home/</i>\n\n<b>%r</b> will be replaced by the rank of the photo. If the photo is unranked, %r will be replaced by '0'. If the photo is in the trash bin, %r will be replaced by 'x'.\n\nIf you want to save the output image where the original is, write:\n<b>%p1/%f</b>\n\nIf you want to save the output image in a directory named "<i>converted</i>" located in the directory of the opened image, write:\n<b>%p1/converted/%f</b>\n\nIf you want to save the output image in a directory named "<i>/home/tom/photos/converted/2010-10-31</i>", write:\n<b>%p2/converted/%d1/%f</b> PREFERENCES_OUTDIRTEMPLATEHINT;You can use the following formatting strings:\n<b>%f</b>, <b>%d1</b>, <b>%d2</b>, ..., <b>%p1</b>, <b>%p2</b>, ..., <b>%r</b>, <b>%s1</b>, <b>%s2</b>, ...\n\nThese formatting strings refer to the different parts of the photo's pathname, some attributes of the photo or an arbitrary sequence index in the batch job.\n\nFor example, if the photo being processed has the following pathname:\n<b><i>/home/tom/photos/2010-10-31/dsc0042.nef</i></b>\nthe meaning of the formatting strings are:\n<b>%d4</b> = <i>home</i>\n<b>%d3</b> = <i>tom</i>\n<b>%d2</b> = <i>photos</i>\n<b>%d1</b> = <i>2010-10-31</i>\n<b>%f</b> = <i>dsc0042</i>\n<b>%p1</b> = <i>/home/tom/photos/2010-10-31/</i>\n<b>%p2</b> = <i>/home/tom/photos/</i>\n<b>%p3</b> = <i>/home/tom/</i>\n<b>%p4</b> = <i>/home/</i>\n\n<b>%r</b> will be replaced by the rank of the photo. If the photo is unranked, %r will be replaced by '0'. If the photo is in the trash bin, %r will be replaced by 'x'.\n\n<b>%s1</b>, <b>%s2</b>, etc. will be replaced by a sequence index which is padded to between 1 and 9 digits. The sequence index will start at one each time the queue processing is started and is incremented by one for each image processed.\n\nIf you want to save the output image where the original is, write:\n<b>%p1/%f</b>\n\nIf you want to save the output image in a directory named "<i>converted</i>" located in the directory of the opened image, write:\n<b>%p1/converted/%f</b>\n\nIf you want to save the output image in a directory named "<i>/home/tom/photos/converted/2010-10-31</i>", write:\n<b>%p2/converted/%d1/%f</b>
PREFERENCES_OUTDIRTEMPLATE;Use template PREFERENCES_OUTDIRTEMPLATE;Use template
PREFERENCES_OUTDIR;Output Directory PREFERENCES_OUTDIR;Output Directory
PREFERENCES_OVERLAY_FILENAMES;Overlay filenames on thumbnails PREFERENCES_OVERLAY_FILENAMES;Overlay filenames on thumbnails

View File

@@ -21,6 +21,10 @@
#include <cstring> #include <cstring>
#include "../rtengine/rt_math.h" #include "../rtengine/rt_math.h"
#include <iomanip>
#include <sstream>
#include <string>
#include "batchqueue.h" #include "batchqueue.h"
#include "multilangmgr.h" #include "multilangmgr.h"
#include "filecatalog.h" #include "filecatalog.h"
@@ -32,7 +36,7 @@
using namespace std; using namespace std;
using namespace rtengine; using namespace rtengine;
BatchQueue::BatchQueue () : processing(NULL), listener(NULL) { BatchQueue::BatchQueue () : processing(NULL), sequence(0), listener(NULL) {
int p = 0; int p = 0;
pmenu = new Gtk::Menu (); pmenu = new Gtk::Menu ();
@@ -52,6 +56,14 @@ BatchQueue::BatchQueue () : processing(NULL), listener(NULL) {
pmenu->show_all (); pmenu->show_all ();
// Accelerators
pmaccelgroup = Gtk::AccelGroup::create ();
pmenu->set_accel_group (pmaccelgroup);
selall->add_accelerator ("activate", pmenu->get_accel_group(), GDK_a, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
head->add_accelerator ("activate", pmenu->get_accel_group(), GDK_Home, (Gdk::ModifierType)0, Gtk::ACCEL_VISIBLE);
tail->add_accelerator ("activate", pmenu->get_accel_group(), GDK_End, (Gdk::ModifierType)0, Gtk::ACCEL_VISIBLE);
cancel->add_accelerator ("activate", pmenu->get_accel_group(), GDK_Delete, (Gdk::ModifierType)0, Gtk::ACCEL_VISIBLE);
cancel->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &BatchQueue::cancelItems), &selected)); cancel->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &BatchQueue::cancelItems), &selected));
head->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &BatchQueue::headItems), &selected)); head->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &BatchQueue::headItems), &selected));
tail->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &BatchQueue::tailItems), &selected)); tail->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &BatchQueue::tailItems), &selected));
@@ -101,6 +113,29 @@ void BatchQueue::rightClicked (ThumbBrowserEntryBase* entry) {
pmenu->popup (3, this->eventTime); pmenu->popup (3, this->eventTime);
} }
bool BatchQueue::keyPressed (GdkEventKey* event) {
bool ctrl = event->state & GDK_CONTROL_MASK;
if ((event->keyval==GDK_A || event->keyval==GDK_a) && ctrl) {
selectAll ();
return true;
}
else if (event->keyval==GDK_Home) {
headItems (&selected);
return true;
}
else if (event->keyval==GDK_End) {
tailItems (&selected);
return true;
}
else if (event->keyval==GDK_Delete) {
cancelItems (&selected);
return true;
}
return false;
}
void BatchQueue::addEntries ( std::vector<BatchQueueEntry*> &entries, bool head, bool save) void BatchQueue::addEntries ( std::vector<BatchQueueEntry*> &entries, bool head, bool save)
{ {
{ {
@@ -501,8 +536,9 @@ void BatchQueue::startProcessing () {
BatchQueueEntry* next; BatchQueueEntry* next;
next = static_cast<BatchQueueEntry*>(fd[0]); next = static_cast<BatchQueueEntry*>(fd[0]);
// tag it as processing // tag it as processing and set sequence
next->processing = true; next->processing = true;
next->sequence = sequence = 1;
processing = next; processing = next;
// remove from selection // remove from selection
if (processing->selected) { if (processing->selected) {
@@ -532,7 +568,7 @@ rtengine::ProcessingJob* BatchQueue::imageReady (rtengine::IImage16* img) {
Glib::ustring fname; Glib::ustring fname;
SaveFormat saveFormat; SaveFormat saveFormat;
if (processing->outFileName=="") { // auto file name if (processing->outFileName=="") { // auto file name
Glib::ustring s = calcAutoFileNameBase (processing->filename); Glib::ustring s = calcAutoFileNameBase (processing->filename, processing->sequence);
saveFormat = options.saveFormatBatch; saveFormat = options.saveFormatBatch;
fname = autoCompleteFileName (s, saveFormat.format); fname = autoCompleteFileName (s, saveFormat.format);
} }
@@ -592,8 +628,9 @@ rtengine::ProcessingJob* BatchQueue::imageReady (rtengine::IImage16* img) {
} }
else if (listener && listener->canStartNext ()) { else if (listener && listener->canStartNext ()) {
BatchQueueEntry* next = static_cast<BatchQueueEntry*>(fd[0]); BatchQueueEntry* next = static_cast<BatchQueueEntry*>(fd[0]);
// tag it as selected // tag it as selected and set sequence
next->processing = true; next->processing = true;
next->sequence = ++sequence;
processing = next; processing = next;
// remove from selection // remove from selection
if (processing->selected) { if (processing->selected) {
@@ -640,7 +677,7 @@ rtengine::ProcessingJob* BatchQueue::imageReady (rtengine::IImage16* img) {
// Calculates automatic filename of processed batch entry, but just the base name // Calculates automatic filename of processed batch entry, but just the base name
// example output: "c:\out\converted\dsc0121" // example output: "c:\out\converted\dsc0121"
Glib::ustring BatchQueue::calcAutoFileNameBase (const Glib::ustring& origFileName) { Glib::ustring BatchQueue::calcAutoFileNameBase (const Glib::ustring& origFileName, int sequence) {
std::vector<Glib::ustring> pa; std::vector<Glib::ustring> pa;
std::vector<Glib::ustring> da; std::vector<Glib::ustring> da;
@@ -717,6 +754,19 @@ Glib::ustring BatchQueue::calcAutoFileNameBase (const Glib::ustring& origFileNam
rank = '0'; // if param file not loaded (e.g. does not exist), default to rank=0 rank = '0'; // if param file not loaded (e.g. does not exist), default to rank=0
path += rank; path += rank;
} }
else if (options.savePathTemplate[ix]=='s') { // sequence
std::ostringstream seqstr;
int w = options.savePathTemplate[ix+1]-'0';
if (w>=1 && w<=9) {
ix++;
seqstr << std::setw (w) << std::setfill ('0');
}
seqstr << sequence;
path += seqstr.str ();
}
} }
else else

View File

@@ -44,6 +44,7 @@ class BatchQueue : public ThumbBrowserBase,
int getThumbnailHeight (); int getThumbnailHeight ();
BatchQueueEntry* processing; // holds the currently processed image BatchQueueEntry* processing; // holds the currently processed image
int sequence; // holds the current sequence index
Glib::ustring nameTemplate; Glib::ustring nameTemplate;
@@ -53,6 +54,8 @@ class BatchQueue : public ThumbBrowserBase,
Gtk::MenuItem* selall; Gtk::MenuItem* selall;
Gtk::Menu* pmenu; Gtk::Menu* pmenu;
Glib::RefPtr<Gtk::AccelGroup> pmaccelgroup;
BatchQueueListener* listener; BatchQueueListener* listener;
Glib::ustring autoCompleteFileName (const Glib::ustring& fileName, const Glib::ustring& format); Glib::ustring autoCompleteFileName (const Glib::ustring& fileName, const Glib::ustring& format);
@@ -84,6 +87,7 @@ class BatchQueue : public ThumbBrowserBase,
rtengine::ProcessingJob* imageReady (rtengine::IImage16* img); rtengine::ProcessingJob* imageReady (rtengine::IImage16* img);
void setProgress (double p); void setProgress (double p);
void rightClicked (ThumbBrowserEntryBase* entry); void rightClicked (ThumbBrowserEntryBase* entry);
bool keyPressed (GdkEventKey* event);
void buttonPressed (LWButton* button, int actionCode, void* actionData); void buttonPressed (LWButton* button, int actionCode, void* actionData);
void redrawNeeded (LWButton* button); void redrawNeeded (LWButton* button);
@@ -92,7 +96,7 @@ class BatchQueue : public ThumbBrowserBase,
bool loadBatchQueue (); bool loadBatchQueue ();
void resizeLoadedQueue(); void resizeLoadedQueue();
static Glib::ustring calcAutoFileNameBase (const Glib::ustring& origFileName); static Glib::ustring calcAutoFileNameBase (const Glib::ustring& origFileName, int sequence = 0);
static int calcMaxThumbnailHeight(); static int calcMaxThumbnailHeight();
}; };

View File

@@ -30,7 +30,7 @@ Glib::RefPtr<Gdk::Pixbuf> BatchQueueEntry::savedAsIcon;
BatchQueueEntry::BatchQueueEntry (rtengine::ProcessingJob* pjob, const rtengine::procparams::ProcParams& pparams, Glib::ustring fname, int prevw, int prevh, Thumbnail* thm) BatchQueueEntry::BatchQueueEntry (rtengine::ProcessingJob* pjob, const rtengine::procparams::ProcParams& pparams, Glib::ustring fname, int prevw, int prevh, Thumbnail* thm)
: ThumbBrowserEntryBase(fname), : ThumbBrowserEntryBase(fname),
opreview(NULL), origpw(prevw), origph(prevh), opreviewDone(false), opreview(NULL), origpw(prevw), origph(prevh), opreviewDone(false),
job(pjob), progress(0), outFileName(""), forceFormatOpts(false) { job(pjob), progress(0), outFileName(""), sequence(0), forceFormatOpts(false) {
thumbnail=thm; thumbnail=thm;
params = pparams; params = pparams;

View File

@@ -49,6 +49,7 @@ public:
Glib::ustring savedParamsFile; Glib::ustring savedParamsFile;
double progress; double progress;
Glib::ustring outFileName; Glib::ustring outFileName;
int sequence;
SaveFormat saveFormat; SaveFormat saveFormat;
bool forceFormatOpts; bool forceFormatOpts;

View File

@@ -274,3 +274,7 @@ void BatchQueuePanel::formatChanged (Glib::ustring f) {
options.saveFormatBatch = saveFormatPanel->getFormat (); options.saveFormatBatch = saveFormatPanel->getFormat ();
} }
bool BatchQueuePanel::handleShortcutKey (GdkEventKey* event) {
return batchQueue->keyPressed (event);
}

View File

@@ -68,6 +68,8 @@ class BatchQueuePanel : public Gtk::VBox,
void pathFolderChanged (); void pathFolderChanged ();
void formatChanged (Glib::ustring f); void formatChanged (Glib::ustring f);
void updateTab (int qsize); void updateTab (int qsize);
bool handleShortcutKey (GdkEventKey* event);
}; };
#endif #endif

View File

@@ -421,7 +421,7 @@ bool RTWindow::keyPressed (GdkEventKey* event) {
return fpanel->handleShortcutKey (event); return fpanel->handleShortcutKey (event);
} }
else if (mainNB->get_current_page() == mainNB->page_num(*bpanel)) { else if (mainNB->get_current_page() == mainNB->page_num(*bpanel)) {
return false; return bpanel->handleShortcutKey (event);
} }
else { else {
EditorPanel* ep = static_cast<EditorPanel*>(mainNB->get_nth_page (mainNB->get_current_page())); EditorPanel* ep = static_cast<EditorPanel*>(mainNB->get_nth_page (mainNB->get_current_page()));