From 7cb8fc92e422d8e8ed4e3f6942e4a2d0082622c0 Mon Sep 17 00:00:00 2001 From: michael Date: Sun, 30 Jun 2013 08:30:52 -0400 Subject: [PATCH] Batch queue improvements: keyboard shortcuts and a sequence index; on behalf of Adam Reichold (issue 1915) --- rtdata/languages/default | 2 +- rtgui/batchqueue.cc | 60 ++++++++++++++++++++++++++++++++++++---- rtgui/batchqueue.h | 6 +++- rtgui/batchqueueentry.cc | 2 +- rtgui/batchqueueentry.h | 1 + rtgui/batchqueuepanel.cc | 4 +++ rtgui/batchqueuepanel.h | 2 ++ rtgui/rtwindow.cc | 2 +- 8 files changed, 70 insertions(+), 9 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index 7fab65713..867e7b31d 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -783,7 +783,7 @@ PREFERENCES_MULTITAB;Multiple Editor Tabs Mode PREFERENCES_OUTDIRFOLDERHINT;Put the saved images to the selected folder PREFERENCES_OUTDIRFOLDER;Save to folder PREFERENCES_OUTDIRHINT;You can use the following formatting strings:\n%f, %d1, %d2, ..., %p1, %p2, ..., %r\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/home/tom/photos/2010-10-31/dsc0042.nef\nthe meaning of the formatting strings are:\n%d4 = home\n%d3 = tom\n%d2 = photos\n%d1 = 2010-10-31\n%f = dsc0042\n%p1 = /home/tom/photos/2010-10-31/\n%p2 = /home/tom/photos/\n%p3 = /home/tom/\n%p4 = /home/\n\n%r 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%p1/%f\n\nIf you want to save the output image in a directory named "converted" located in the directory of the opened image, write:\n%p1/converted/%f\n\nIf you want to save the output image in a directory named "/home/tom/photos/converted/2010-10-31", write:\n%p2/converted/%d1/%f -PREFERENCES_OUTDIRTEMPLATEHINT;You can use the following formatting strings:\n%f, %d1, %d2, ..., %p1, %p2, ..., %r\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/home/tom/photos/2010-10-31/dsc0042.nef\nthe meaning of the formatting strings are:\n%d4 = home\n%d3 = tom\n%d2 = photos\n%d1 = 2010-10-31\n%f = dsc0042\n%p1 = /home/tom/photos/2010-10-31/\n%p2 = /home/tom/photos/\n%p3 = /home/tom/\n%p4 = /home/\n\n%r 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%p1/%f\n\nIf you want to save the output image in a directory named "converted" located in the directory of the opened image, write:\n%p1/converted/%f\n\nIf you want to save the output image in a directory named "/home/tom/photos/converted/2010-10-31", write:\n%p2/converted/%d1/%f +PREFERENCES_OUTDIRTEMPLATEHINT;You can use the following formatting strings:\n%f, %d1, %d2, ..., %p1, %p2, ..., %r, %s1, %s2, ...\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/home/tom/photos/2010-10-31/dsc0042.nef\nthe meaning of the formatting strings are:\n%d4 = home\n%d3 = tom\n%d2 = photos\n%d1 = 2010-10-31\n%f = dsc0042\n%p1 = /home/tom/photos/2010-10-31/\n%p2 = /home/tom/photos/\n%p3 = /home/tom/\n%p4 = /home/\n\n%r 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%s1, %s2, 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%p1/%f\n\nIf you want to save the output image in a directory named "converted" located in the directory of the opened image, write:\n%p1/converted/%f\n\nIf you want to save the output image in a directory named "/home/tom/photos/converted/2010-10-31", write:\n%p2/converted/%d1/%f PREFERENCES_OUTDIRTEMPLATE;Use template PREFERENCES_OUTDIR;Output Directory PREFERENCES_OVERLAY_FILENAMES;Overlay filenames on thumbnails diff --git a/rtgui/batchqueue.cc b/rtgui/batchqueue.cc index 8529634a1..5a3eabf51 100644 --- a/rtgui/batchqueue.cc +++ b/rtgui/batchqueue.cc @@ -21,6 +21,10 @@ #include #include "../rtengine/rt_math.h" +#include +#include +#include + #include "batchqueue.h" #include "multilangmgr.h" #include "filecatalog.h" @@ -32,7 +36,7 @@ using namespace std; using namespace rtengine; -BatchQueue::BatchQueue () : processing(NULL), listener(NULL) { +BatchQueue::BatchQueue () : processing(NULL), sequence(0), listener(NULL) { int p = 0; pmenu = new Gtk::Menu (); @@ -51,6 +55,14 @@ BatchQueue::BatchQueue () : processing(NULL), listener(NULL) { cancel->set_image(*Gtk::manage(new RTImage ("gtk-close.png"))); 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)); head->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &BatchQueue::headItems), &selected)); @@ -101,6 +113,29 @@ void BatchQueue::rightClicked (ThumbBrowserEntryBase* entry) { 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 &entries, bool head, bool save) { { @@ -501,8 +536,9 @@ void BatchQueue::startProcessing () { BatchQueueEntry* next; next = static_cast(fd[0]); - // tag it as processing + // tag it as processing and set sequence next->processing = true; + next->sequence = sequence = 1; processing = next; // remove from selection if (processing->selected) { @@ -532,7 +568,7 @@ rtengine::ProcessingJob* BatchQueue::imageReady (rtengine::IImage16* img) { Glib::ustring fname; SaveFormat saveFormat; if (processing->outFileName=="") { // auto file name - Glib::ustring s = calcAutoFileNameBase (processing->filename); + Glib::ustring s = calcAutoFileNameBase (processing->filename, processing->sequence); saveFormat = options.saveFormatBatch; fname = autoCompleteFileName (s, saveFormat.format); } @@ -592,8 +628,9 @@ rtengine::ProcessingJob* BatchQueue::imageReady (rtengine::IImage16* img) { } else if (listener && listener->canStartNext ()) { BatchQueueEntry* next = static_cast(fd[0]); - // tag it as selected + // tag it as selected and set sequence next->processing = true; + next->sequence = ++sequence; processing = next; // remove from selection 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 // 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 pa; std::vector 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 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 diff --git a/rtgui/batchqueue.h b/rtgui/batchqueue.h index e9bd78fd3..e435407a8 100644 --- a/rtgui/batchqueue.h +++ b/rtgui/batchqueue.h @@ -44,6 +44,7 @@ class BatchQueue : public ThumbBrowserBase, int getThumbnailHeight (); BatchQueueEntry* processing; // holds the currently processed image + int sequence; // holds the current sequence index Glib::ustring nameTemplate; @@ -52,6 +53,8 @@ class BatchQueue : public ThumbBrowserBase, Gtk::ImageMenuItem* tail; Gtk::MenuItem* selall; Gtk::Menu* pmenu; + + Glib::RefPtr pmaccelgroup; BatchQueueListener* listener; @@ -84,6 +87,7 @@ class BatchQueue : public ThumbBrowserBase, rtengine::ProcessingJob* imageReady (rtengine::IImage16* img); void setProgress (double p); void rightClicked (ThumbBrowserEntryBase* entry); + bool keyPressed (GdkEventKey* event); void buttonPressed (LWButton* button, int actionCode, void* actionData); void redrawNeeded (LWButton* button); @@ -92,7 +96,7 @@ class BatchQueue : public ThumbBrowserBase, bool loadBatchQueue (); void resizeLoadedQueue(); - static Glib::ustring calcAutoFileNameBase (const Glib::ustring& origFileName); + static Glib::ustring calcAutoFileNameBase (const Glib::ustring& origFileName, int sequence = 0); static int calcMaxThumbnailHeight(); }; diff --git a/rtgui/batchqueueentry.cc b/rtgui/batchqueueentry.cc index aadb6196e..185632b9b 100644 --- a/rtgui/batchqueueentry.cc +++ b/rtgui/batchqueueentry.cc @@ -30,7 +30,7 @@ Glib::RefPtr BatchQueueEntry::savedAsIcon; BatchQueueEntry::BatchQueueEntry (rtengine::ProcessingJob* pjob, const rtengine::procparams::ProcParams& pparams, Glib::ustring fname, int prevw, int prevh, Thumbnail* thm) : ThumbBrowserEntryBase(fname), 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; params = pparams; diff --git a/rtgui/batchqueueentry.h b/rtgui/batchqueueentry.h index 4df6388a9..7c2b360ce 100644 --- a/rtgui/batchqueueentry.h +++ b/rtgui/batchqueueentry.h @@ -49,6 +49,7 @@ public: Glib::ustring savedParamsFile; double progress; Glib::ustring outFileName; + int sequence; SaveFormat saveFormat; bool forceFormatOpts; diff --git a/rtgui/batchqueuepanel.cc b/rtgui/batchqueuepanel.cc index dcad1dd62..a6f18852e 100644 --- a/rtgui/batchqueuepanel.cc +++ b/rtgui/batchqueuepanel.cc @@ -274,3 +274,7 @@ void BatchQueuePanel::formatChanged (Glib::ustring f) { options.saveFormatBatch = saveFormatPanel->getFormat (); } + +bool BatchQueuePanel::handleShortcutKey (GdkEventKey* event) { + return batchQueue->keyPressed (event); +} diff --git a/rtgui/batchqueuepanel.h b/rtgui/batchqueuepanel.h index 2f37a3ed2..e46348fc5 100644 --- a/rtgui/batchqueuepanel.h +++ b/rtgui/batchqueuepanel.h @@ -68,6 +68,8 @@ class BatchQueuePanel : public Gtk::VBox, void pathFolderChanged (); void formatChanged (Glib::ustring f); void updateTab (int qsize); + + bool handleShortcutKey (GdkEventKey* event); }; #endif diff --git a/rtgui/rtwindow.cc b/rtgui/rtwindow.cc index 000b57c86..1cea7b2b4 100644 --- a/rtgui/rtwindow.cc +++ b/rtgui/rtwindow.cc @@ -421,7 +421,7 @@ bool RTWindow::keyPressed (GdkEventKey* event) { return fpanel->handleShortcutKey (event); } else if (mainNB->get_current_page() == mainNB->page_num(*bpanel)) { - return false; + return bpanel->handleShortcutKey (event); } else { EditorPanel* ep = static_cast(mainNB->get_nth_page (mainNB->get_current_page()));