/* * This file is part of RawTherapee. * * Copyright (c) 2004-2010 Gabor Horvath * * RawTherapee 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 3 of the License, or * (at your option) any later version. * * RawTherapee 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. * * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ #include #include #include #include #include #include using namespace rtengine; BatchQueue::BatchQueue () : processing(NULL), listener(NULL) { int p = 0; pmenu = new Gtk::Menu (); pmenu->attach (*(cancel = new Gtk::MenuItem (M("FILEBROWSER_POPUPCANCELJOB"))), 0, 1, p, p+1); p++; pmenu->attach (*(new Gtk::SeparatorMenuItem ()), 0, 1, p, p+1); p++; pmenu->attach (*(head = new Gtk::MenuItem (M("FILEBROWSER_POPUPMOVEHEAD"))), 0, 1, p, p+1); p++; pmenu->attach (*(tail = new Gtk::MenuItem (M("FILEBROWSER_POPUPMOVEEND"))), 0, 1, p, p+1); p++; pmenu->attach (*(new Gtk::SeparatorMenuItem ()), 0, 1, p, p+1); p++; pmenu->attach (*(selall = new Gtk::MenuItem (M("FILEBROWSER_POPUPSELECTALL"))), 0, 1, p, p+1); p++; pmenu->show_all (); 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)); tail->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &BatchQueue::tailItems), &selected)); selall->signal_activate().connect (sigc::mem_fun(*this, &BatchQueue::selectAll)); } void BatchQueue::rightClicked (ThumbBrowserEntryBase* entry) { pmenu->popup (3, 0); } void BatchQueue::addEntry (BatchQueueEntry* entry, bool head) { entry->setParent (this); entry->resize (options.thumbSize); entry->selected = false; if (!head) fd.push_back (entry); else { std::vector::iterator pos; for (pos=fd.begin(); pos!=fd.end(); pos++) if (!(*pos)->processing) { fd.insert (pos, entry); break; } if (pos==fd.end()) fd.push_back (entry); } if (entry->thumbnail) entry->thumbnail->imageEnqueued (); BatchQueueButtonSet* bqbs = new BatchQueueButtonSet (entry); bqbs->setButtonListener (this); entry->addButtonSet (bqbs); arrangeFiles (); queue_draw (); notifyListener (); } int deleteitem (void* data) { gdk_threads_enter (); delete (BatchQueueEntry*)data; gdk_threads_leave (); return 0; } void BatchQueue::cancelItems (std::vector* items) { for (int i=0; isize(); i++) { BatchQueueEntry* entry = (BatchQueueEntry*)(*items)[i]; if (entry->processing) continue; std::vector::iterator pos = std::find (fd.begin(), fd.end(), entry); if (pos!=fd.end()) { fd.erase (pos); rtengine::ProcessingJob::destroy (entry->job); if (entry->thumbnail) entry->thumbnail->imageRemovedFromQueue (); g_idle_add (deleteitem, entry); } } for (int i=0; iselected = false; lastClicked = NULL; selected.clear (); redraw (); notifyListener (); } void BatchQueue::headItems (std::vector* items) { for (int i=items->size()-1; i>=0; i--) { BatchQueueEntry* entry = (BatchQueueEntry*)(*items)[i]; if (entry->processing) continue; std::vector::iterator pos = std::find (fd.begin(), fd.end(), entry); if (pos!=fd.end() && pos!=fd.begin()) { fd.erase (pos); // find the first item that is not under processing for (pos=fd.begin(); pos!=fd.end(); pos++) if (!(*pos)->processing) { fd.insert (pos, entry); break; } } } redraw (); } void BatchQueue::tailItems (std::vector* items) { for (int i=0; isize(); i++) { BatchQueueEntry* entry = (BatchQueueEntry*)(*items)[i]; if (entry->processing) continue; std::vector::iterator pos = std::find (fd.begin(), fd.end(), entry); if (pos!=fd.end()) { fd.erase (pos); fd.push_back (entry); } } redraw (); } void BatchQueue::selectAll () { lastClicked = NULL; selected.clear (); for (int i=0; iprocessing) continue; fd[i]->selected = true; selected.push_back (fd[i]); } queue_draw (); } void BatchQueue::startProcessing () { if (!processing && fd.size()>0) { BatchQueueEntry* next = (BatchQueueEntry*)fd[0]; // tag it as processing next->processing = true; processing = next; // remove from selection if (processing->selected) { std::vector::iterator pos = std::find (selected.begin(), selected.end(), processing); if (pos!=selected.end()) selected.erase (pos); processing->selected = false; } // remove button set next->removeButtonSet (); // start batch processing rtengine::startBatchProcessing (next->job, this); queue_draw (); } } rtengine::ProcessingJob* BatchQueue::imageReady (rtengine::IImage16* img) { gdk_threads_enter (); // save image img Glib::ustring fname; SaveFormat saveFormat; if (processing->outFileName=="") { // auto file name fname = obtainFileName (processing->filename); saveFormat = options.saveFormat; } else { // use the save-as filename with automatic completion for uniqueness fname = autoCompleteFileName (removeExtension(processing->outFileName), getExtension(processing->outFileName)); saveFormat = processing->saveFormat; } printf ("fname=%s, %s\n", fname.c_str(), removeExtension(fname).c_str()); if (img && fname!="") { int err = 0; if (saveFormat.format=="tif") err = img->saveAsTIFF (fname, saveFormat.tiffBits); else if (saveFormat.format=="png") err = img->saveAsPNG (fname, saveFormat.pngCompression, saveFormat.pngBits); else if (saveFormat.format=="jpg") err = img->saveAsJPEG (fname, saveFormat.jpegQuality); img->free (); if (!err && saveFormat.saveParams) processing->params.save (removeExtension(fname) + paramFileExtension); if (processing->thumbnail) { processing->thumbnail->imageDeveloped (); processing->thumbnail->imageRemovedFromQueue (); if (listener) listener->imageProcessingReady (processing->filename); } } // delete from the queue delete processing; processing = NULL; fd.erase (fd.begin()); // return next job if (fd.size()==0) { if (listener) listener->queueEmpty (); } else if (listener && listener->canStartNext ()) { BatchQueueEntry* next = (BatchQueueEntry*)fd[0]; // tag it as selected next->processing = true; processing = next; // remove from selection if (processing->selected) { std::vector::iterator pos = std::find (selected.begin(), selected.end(), processing); if (pos!=selected.end()) selected.erase (pos); processing->selected = false; } // remove button set next->removeButtonSet (); } redraw (); notifyListener (); gdk_threads_leave (); return processing ? processing->job : NULL; } Glib::ustring BatchQueue::obtainFileName (const Glib::ustring& origFileName) { std::vector pa; std::vector da; for (int i=0; i=origFileName.size()) break; Glib::ustring tok = ""; while ((i=0 && origFileName[extpos]!='.'; extpos--); for (int k=extpos-1; k>=0 && origFileName[k]!='/' && origFileName[k]!='\\'; k--) filename = origFileName[k] + filename; // printf ("%d, |%s|\n", extpos, filename.c_str()); // constructing full output path // printf ("path=|%s|\n", options.savePath.c_str()); Glib::ustring path=""; if (options.saveUsePathTemplate) { int ix=0; while (options.savePathTemplate[ix]!=0) { if (options.savePathTemplate[ix]=='%') { ix++; if (options.savePathTemplate[ix]=='p') { ix++; int i = options.savePathTemplate[ix]-'0'; if (iredraw(); gdk_threads_leave (); return 0; } void BatchQueue::setProgress (double p) { if (processing) processing->progress = p; g_idle_add (bqredraw, this); } void BatchQueue::buttonPressed (LWButton* button, int actionCode, void* actionData) { std::vector bqe; bqe.push_back ((BatchQueueEntry*)actionData); if (actionCode==10) // cancel cancelItems (&bqe); else if (actionCode==8) // to head headItems (&bqe); else if (actionCode==9) // to tail tailItems (&bqe); } struct NLParams { BatchQueueListener* listener; int qsize; }; int bqnotifylistener (void* data) { gdk_threads_enter (); NLParams* params = (NLParams*)data; params->listener->queueSizeChanged (params->qsize); delete params; gdk_threads_leave (); return 0; } void BatchQueue::notifyListener () { if (listener) { NLParams* params = new NLParams; params->listener = listener; params->qsize = fd.size(); g_idle_add (bqnotifylistener, params); } } void BatchQueue::redrawNeeded (LWButton* button) { queue_draw (); }