Proper check for rawzor libraries.
[rawtherapee-fixes.git] / rtgui / editorpanel.cc
blob70b1095f84a82ca9b7526395f73da5900613795f
1 /*
2 * This file is part of RawTherapee.
4 * Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
6 * RawTherapee is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * RawTherapee is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
19 #include <editorpanel.h>
20 #include <options.h>
21 #include <progressdialog.h>
22 #include <rtwindow.h>
23 #include <guiutils.h>
24 #include <procparamchangers.h>
25 #include "config.h"
27 using namespace rtengine::procparams;
29 EditorPanel::EditorPanel (Thumbnail* tmb, rtengine::InitialImage* isrc) : parent(NULL), beforeIarea(NULL), beforePreviewHandler(NULL), beforeIpc(NULL) {
31 epih = new EditorPanelIdleHelper;
32 epih->epanel = this;
33 epih->destroyed = false;
34 epih->pending = 0;
36 // construct toolpanelcoordinator
37 tpc = new ToolPanelCoordinator ();
39 // build GUI
40 // build left side panel
41 leftbox = Gtk::manage (new Gtk::VBox ());
42 leftbox->set_border_width (4);
44 histogramPanel = Gtk::manage (new HistogramPanel ());
45 histogramPanel->set_size_request (-1, 150);
46 // leftbox->pack_start (*histogramPanel, Gtk::PACK_SHRINK, 4);
48 profilep = Gtk::manage (new ProfilePanel ());
49 Gtk::Frame* ppframe = Gtk::manage (new Gtk::Frame ());
50 ppframe->add (*profilep);
51 ppframe->set_label (M("PROFILEPANEL_LABEL"));
52 // leftbox->pack_start (*ppframe, Gtk::PACK_SHRINK, 4);
54 navigator = Gtk::manage (new Navigator ());
55 navigator->previewWindow->set_size_request (-1, 150);
56 leftbox->pack_start (*navigator, Gtk::PACK_SHRINK, 4);
58 history = Gtk::manage (new History ());
59 leftbox->pack_start (*history);
61 leftbox->show_all ();
63 // build the middle of the screen
64 Gtk::VBox* editbox = Gtk::manage (new Gtk::VBox ());
66 info = Gtk::manage (new Gtk::ToggleButton ());
67 Gtk::Image* infoimg = Gtk::manage (new Gtk::Image (GET_DATA_PATH(argv0)+"/images/info.png"));
68 info->add (*infoimg);
69 info->set_relief(Gtk::RELIEF_NONE);
70 info->set_tooltip_text (M("MAIN_TOOLTIP_QINFO"));
72 beforeAfter = Gtk::manage (new Gtk::ToggleButton ("B|A"));
73 beforeAfter->set_tooltip_text ("Toggle before/after view");
76 Gtk::VSeparator* vsept = Gtk::manage (new Gtk::VSeparator ());
77 Gtk::VSeparator* vsepz = Gtk::manage (new Gtk::VSeparator ());
78 Gtk::VSeparator* vsepi = Gtk::manage (new Gtk::VSeparator ());
79 Gtk::VSeparator* vseph = Gtk::manage (new Gtk::VSeparator ());
81 hidehp = Gtk::manage (new Gtk::ToggleButton ());
82 Gtk::Label* hidehpLabel = Gtk::manage (new Gtk::Label ());
83 hidehpLabel->set_markup ("<b>H</b>");
84 Gtk::Image* hpimg = Gtk::manage (new Gtk::Image (GET_DATA_PATH(argv0)+"/images/left.png"));
85 Gtk::HBox* hidehpBox = Gtk::manage (new Gtk::HBox ());
86 hidehpBox->pack_start (*hpimg, Gtk::PACK_SHRINK, 2);
87 hidehpBox->pack_start (*hidehpLabel, Gtk::PACK_SHRINK, 2);
88 hidehp->add (*hidehpBox);
89 hidehp->set_relief(Gtk::RELIEF_NONE);
90 hidehp->set_active (options.showHistory);
91 hidehp->set_tooltip_text (M("MAIN_TOOLTIP_HIDEHP"));
93 Gtk::VSeparator* vsepcl = Gtk::manage (new Gtk::VSeparator ());
94 Gtk::VSeparator* vsepz2 = Gtk::manage (new Gtk::VSeparator ());
96 iarea = new ImageAreaPanel ();
98 Gtk::HBox* toolBarPanel = Gtk::manage (new Gtk::HBox ());
99 toolBarPanel->pack_start (*hidehp, Gtk::PACK_SHRINK, 1);
100 toolBarPanel->pack_start (*vseph, Gtk::PACK_SHRINK, 2);
101 toolBarPanel->pack_start (*info, Gtk::PACK_SHRINK, 1);
102 toolBarPanel->pack_start (*beforeAfter, Gtk::PACK_SHRINK, 1);
103 toolBarPanel->pack_start (*vsepi, Gtk::PACK_SHRINK, 2);
104 toolBarPanel->pack_start (*tpc->getToolBar(), Gtk::PACK_SHRINK, 1);
105 toolBarPanel->pack_start (*vsept, Gtk::PACK_SHRINK, 2);
106 toolBarPanel->pack_end (*tpc->coarse, Gtk::PACK_SHRINK, 4);
107 toolBarPanel->pack_end (*vsepcl, Gtk::PACK_SHRINK, 4);
108 toolBarPanel->pack_end (*iarea->imageArea->indClippedPanel, Gtk::PACK_SHRINK, 0);
109 toolBarPanel->pack_end (*vsepz, Gtk::PACK_SHRINK, 2);
111 afterBox = Gtk::manage (new Gtk::VBox ());
112 afterBox->pack_start (*iarea);
114 beforeAfterBox = Gtk::manage (new Gtk::HBox());
115 beforeAfterBox->pack_start (*afterBox);
117 editbox->pack_start (*toolBarPanel, Gtk::PACK_SHRINK);
118 editbox->pack_start (*beforeAfterBox);
120 // build right side panel
121 vboxright = Gtk::manage (new Gtk::VBox (false, 0));
122 vboxright->set_border_width (4);
123 vboxright->pack_start (*histogramPanel, Gtk::PACK_SHRINK, 4);
124 vboxright->pack_start (*ppframe, Gtk::PACK_SHRINK, 4);
125 // main notebook
126 vboxright->pack_start (*tpc->toolPanelNotebook);
128 // buttons & status
129 Gtk::HBox* iops = Gtk::manage (new Gtk::HBox ());
130 saveimgas = Gtk::manage (new Gtk::Button (M("MAIN_BUTTON_SAVE")));
131 saveimgas->set_image (*Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-save"), Gtk::ICON_SIZE_BUTTON)));
132 queueimg = Gtk::manage (new Gtk::Button ("Put to queue"));
133 queueimg->set_image (*Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-execute"), Gtk::ICON_SIZE_BUTTON)));
134 sendtogimp = Gtk::manage (new Gtk::Button (M("MAIN_BUTTON_SENDTOEDITOR")));
135 sendtogimp->set_image (*Gtk::manage(new Gtk::Image (GET_DATA_PATH(argv0)+"/images/gimp.png")));
136 iops->pack_start (*saveimgas, Gtk::PACK_SHRINK);
137 iops->pack_start (*queueimg, Gtk::PACK_SHRINK);
138 iops->pack_start (*sendtogimp, Gtk::PACK_SHRINK);
140 statusBox = Gtk::manage (new Gtk::HBox ());
141 progressLabel = Gtk::manage (new Gtk::Label(""));
142 statusBox->pack_start (*progressLabel);
143 red = new Gtk::Image (GET_DATA_PATH(argv0)+"/images/red.png");
144 green = new Gtk::Image (GET_DATA_PATH(argv0)+"/images/green.png");
145 red->show ();
146 green->show ();
147 statusBox->pack_end (*green, Gtk::PACK_SHRINK, 4);
148 iops->pack_start(*statusBox, Gtk::PACK_SHRINK, 4);
150 iops->pack_end (*iarea->imageArea->zoomPanel, Gtk::PACK_SHRINK, 1);
151 iops->pack_end (*vsepz2, Gtk::PACK_SHRINK, 2);
154 editbox->pack_start (*Gtk::manage(new Gtk::HSeparator()), Gtk::PACK_SHRINK, 4);
155 editbox->pack_start (*iops, Gtk::PACK_SHRINK, 4);
156 editbox->show_all ();
158 // build screen
159 hpanedl = Gtk::manage (new Gtk::HPaned());
160 hpanedr = Gtk::manage (new Gtk::HPaned());
161 leftbox->reference ();
162 vboxright->reference ();
163 if (options.showHistory) {
164 hpanedl->pack1(*leftbox, false, true);
165 hpanedl->set_position (options.historyPanelWidth);
168 Gtk::Frame* vbfr = Gtk::manage (new Gtk::Frame ());
169 vbfr->add (*editbox);
170 hpanedl->pack2(*vbfr, true, true);
172 hpanedr->pack1(*hpanedl, true, true);
173 hpanedr->pack2(*vboxright, false, true);
175 pack_start (*hpanedr);
176 show_all ();
178 // save as dialog
179 if (Glib::file_test (options.lastSaveAsPath, Glib::FILE_TEST_IS_DIR))
180 saveAsDialog = new SaveAsDialog (options.lastSaveAsPath);
181 else
182 saveAsDialog = new SaveAsDialog (Glib::get_user_special_dir (G_USER_DIRECTORY_PICTURES));
185 // connect listeners
186 profilep->setProfileChangeListener (tpc);
187 history->setProfileChangeListener (tpc);
188 history->setHistoryBeforeLineListener (this);
189 tpc->addPParamsChangeListener (profilep);
190 tpc->addPParamsChangeListener (history);
191 tpc->addPParamsChangeListener (this);
192 iarea->imageArea->setCropGUIListener (tpc->getCropGUIListener());
193 iarea->imageArea->setPointerMotionListener (navigator);
194 iarea->imageArea->setImageAreaToolListener (tpc);
196 // initialize components
197 info->set_active (options.showInfo);
198 tpc->readOptions ();
200 // connect event handlers
201 info->signal_toggled().connect( sigc::mem_fun(*this, &EditorPanel::info_toggled) );
202 beforeAfter->signal_toggled().connect( sigc::mem_fun(*this, &EditorPanel::beforeAfterToggled) );
203 hidehp->signal_toggled().connect( sigc::mem_fun(*this, &EditorPanel::hideHistoryActivated) );
204 saveimgas->signal_pressed().connect( sigc::mem_fun(*this, &EditorPanel::saveAsPressed) );
205 queueimg->signal_pressed().connect( sigc::mem_fun(*this, &EditorPanel::queueImgPressed) );
206 sendtogimp->signal_pressed().connect( sigc::mem_fun(*this, &EditorPanel::sendToGimpPressed) );
208 // open image
209 open (tmb, isrc);
212 bool EditorPanel::beforeClosing () {
214 options.toolPanelWidth = vboxright->get_width ();
215 return true;
218 EditorPanel::~EditorPanel () {
220 history->setHistoryBeforeLineListener (NULL);
221 // the order is important!
222 delete iarea;
223 delete beforeIarea;
225 if (ipc)
226 ipc->setPreviewImageListener (NULL);
227 if (beforeIpc)
228 beforeIpc->setPreviewImageListener (NULL);
230 delete previewHandler;
231 delete beforePreviewHandler;
233 if (ipc)
234 close ();
236 if (epih->pending)
237 epih->destroyed = true;
238 else
239 delete epih;
241 delete tpc;
243 delete red;
244 delete green;
245 delete leftbox;
246 delete vboxright;
248 delete saveAsDialog;
251 void EditorPanel::on_realize () {
253 Gtk::VBox::on_realize ();
254 vboxright->set_size_request (options.toolPanelWidth, -1);
257 rtengine::InitialImage* EditorPanel::loadImage (Thumbnail* tmb) {
259 // try to load the image
260 Glib::ustring filename = tmb->getFileName ();
261 int error;
262 // InitialImage* isrc = InitialImage::load (filename, tmb->getType()==FT_Raw, error, this);
263 ProgressDialog<rtengine::InitialImage*>* pdload = new ProgressDialog<rtengine::InitialImage*> (M("PROGRESSDLG_LOADING"));
264 rtengine::InitialImage* isrc;
265 pdload->setFunc (sigc::bind(sigc::ptr_fun(&rtengine::InitialImage::load), filename, tmb->getType()==FT_Raw, &error, pdload->getProgressListener()), &isrc);
266 pdload->start ();
267 delete pdload;
269 if (error)
270 return NULL;
271 else
272 return isrc;
275 void EditorPanel::open (Thumbnail* tmb, rtengine::InitialImage* isrc) {
277 // initialize everything
278 openThm = tmb;
279 openThm->increaseRef ();
281 previewHandler = new PreviewHandler ();
283 this->isrc = isrc;
284 ipc = rtengine::StagedImageProcessor::create (isrc);
285 ipc->setProgressListener (this);
286 ipc->setPreviewImageListener (previewHandler);
287 ipc->setPreviewScale (10);
288 tpc->initImage (ipc, tmb->getType()==FT_Raw);
289 ipc->setHistogramListener (histogramPanel);
291 // iarea->fitZoom (); // tell to the editorPanel that the next image has to be fitted to the screen
292 iarea->imageArea->setPreviewHandler (previewHandler);
293 iarea->imageArea->setImProcCoordinator (ipc);
294 navigator->previewWindow->setPreviewHandler (previewHandler);
295 navigator->previewWindow->setImageArea (iarea->imageArea);
297 // try to load the last saved parameters from the cache or from the pp2 file
298 ProcParams* ldprof = NULL;
299 if (openThm->hasProcParams()) {
300 ldprof = new ProcParams ();
301 *ldprof = openThm->getProcParams ();
304 // initialize profile
305 if (openThm->getType()!=FT_Raw)
306 profilep->initProfile (options.defProfImg, ldprof, NULL);
307 else
308 profilep->initProfile (options.defProfRaw, ldprof, NULL);
310 openThm->addThumbnailListener (this);
311 info_toggled ();
314 void EditorPanel::close () {
316 saveProfile ();
318 // close image processor and the current thumbnail
319 tpc->closeImage (); // this call stops image processing
320 tpc->writeOptions ();
322 if (ipc)
323 rtengine::StagedImageProcessor::destroy (ipc);
324 if (beforeIpc)
325 rtengine::StagedImageProcessor::destroy (beforeIpc);
327 openThm->removeThumbnailListener (this);
328 openThm->decreaseRef ();
331 void EditorPanel::saveProfile () {
333 ProcParams params;
334 ipc->getParams (&params);
336 if (options.saveParamsFile)
337 params.save (openThm->getFileName() + ".pp2");
338 if (openThm && options.saveParamsCache)
339 openThm->setProcParams (params, EDITOR);
342 Glib::ustring EditorPanel::getShortName () {
344 return Glib::path_get_basename (openThm->getFileName ());
347 Glib::ustring EditorPanel::getFileName () {
349 return openThm->getFileName ();
352 // TODO!!!
353 void EditorPanel::procParamsChanged (rtengine::procparams::ProcParams* params, rtengine::ProcEvent ev, Glib::ustring descr, ParamsEdited* paramsEdited) {
355 // if (ev!=EvPhotoLoaded)
356 // saveLabel->set_markup (Glib::ustring("<span foreground=\"#AA0000\" weight=\"bold\">") + M("MAIN_BUTTON_SAVE") + "</span>");
359 struct spsparams {
360 bool state;
361 EditorPanelIdleHelper* epih;
364 int setprocstate (void* data) {
366 gdk_threads_enter ();
367 spsparams* p = (spsparams*)data;
369 if (p->epih->destroyed) {
370 if (p->epih->pending == 1)
371 delete p->epih;
372 else
373 p->epih->pending--;
374 delete p;
375 gdk_threads_leave ();
376 return 0;
379 p->epih->epanel->refreshProcessingState (p->state);
380 p->epih->pending--;
381 delete p;
382 gdk_threads_leave ();
383 return 0;
386 void EditorPanel::setProgressState (int state) {
388 epih->pending++;
390 spsparams* p = new spsparams;
391 p->state = state;
392 p->epih = epih;
393 g_idle_add (setprocstate, p);
396 void EditorPanel::refreshProcessingState (bool state) {
398 // Set proc params of thumbnail. It saves it into the cache and updates the file browser.
399 if (ipc && openThm && !state && tpc->getChangedState()) {
400 rtengine::procparams::ProcParams pparams;
401 ipc->getParams (&pparams);
402 openThm->setProcParams (pparams, EDITOR, false);
405 // change state of the led
406 std::vector<Widget*> children = (std::vector<Widget*>) statusBox->get_children();
407 if (children.size()>=1) {
408 Gtk::Widget* wlast = children[children.size()-1];
409 if (wlast)
410 statusBox->remove (*wlast);
412 if (state)
413 statusBox->pack_end (*red, Gtk::PACK_SHRINK, 4);
414 else
415 statusBox->pack_end (*green, Gtk::PACK_SHRINK, 4);
418 struct errparams {
419 Glib::ustring descr;
420 EditorPanelIdleHelper* epih;
423 void EditorPanel::displayError (Glib::ustring descr) {
425 if (parent) {
426 Gtk::MessageDialog* msgd = new Gtk::MessageDialog (*parent, descr, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
427 msgd->set_title (M("MAIN_MSG_CANNOTSAVE"));
428 msgd->run ();
429 delete msgd;
433 int disperror (void* data) {
435 gdk_threads_enter ();
436 errparams* p = (errparams*)data;
438 if (p->epih->destroyed) {
439 if (p->epih->pending == 1)
440 delete p->epih;
441 else
442 p->epih->pending--;
443 delete p;
444 gdk_threads_leave ();
445 return 0;
448 p->epih->epanel->displayError (p->descr);
449 p->epih->pending--;
450 delete p;
451 gdk_threads_leave ();
452 return 0;
455 void EditorPanel::error (Glib::ustring descr) {
457 epih->pending++;
458 errparams* p = new errparams;
459 p->descr = descr;
460 p->epih = epih;
461 g_idle_add (disperror, p);
464 void EditorPanel::info_toggled () {
466 Glib::ustring infoString;
468 const rtengine::ImageMetaData* idata = ipc->getInitialImage()->getMetaData();
469 if (idata && idata->hasExif())
470 infoString = Glib::ustring::compose ("%1 %2\nF/%3 %4 sec\n%5: %6\n%7: %8 mm\n",
471 Glib::ustring(idata->getMake()), Glib::ustring(idata->getModel()),
472 Glib::ustring(idata->apertureToString(idata->getFNumber())), Glib::ustring(idata->shutterToString(idata->getShutterSpeed())),
473 M("QINFO_ISO"), idata->getISOSpeed(),
474 M("QINFO_FOCALLENGTH"), idata->getFocalLen())
475 + Glib::ustring::compose ("%1: %2", M("QINFO_LENS"), Glib::ustring(idata->getLens()));
476 else
477 infoString = M("QINFO_NOEXIF");
479 iarea->imageArea->setInfoText (infoString);
480 iarea->imageArea->infoEnabled (info->get_active ());
483 void EditorPanel::hideHistoryActivated () {
485 removeIfThere (hpanedl, leftbox, false);
486 if (hidehp->get_active())
487 hpanedl->pack1 (*leftbox, false, true);
490 bool EditorPanel::handleShortcutKey (GdkEventKey* event) {
492 if (event->keyval==GDK_H || event->keyval==GDK_h) {
493 hidehp->set_active (!hidehp->get_active());
494 return true;
496 else if ((event->keyval==GDK_Z || event->keyval==GDK_z) && event->state & GDK_CONTROL_MASK && !(event->state & GDK_SHIFT_MASK)) {
497 history->undo ();
498 return true;
500 else if ((event->keyval==GDK_Z || event->keyval==GDK_z) && event->state & GDK_CONTROL_MASK && event->state & GDK_SHIFT_MASK) {
501 history->redo ();
502 return true;
504 else if (event->keyval==GDK_w || event->keyval==GDK_W) {
505 tpc->getToolBar()->wb_pressed ();
506 return true;
508 else if (event->keyval==GDK_c || event->keyval==GDK_C) {
509 tpc->getToolBar()->crop_pressed ();
510 return true;
512 else if (event->keyval==GDK_s || event->keyval==GDK_S) {
513 tpc->getToolBar()->stra_pressed ();
514 return true;
516 else if (event->keyval==GDK_n || event->keyval==GDK_N) {
517 tpc->getToolBar()->hand_pressed ();
518 return true;
520 else
521 return false;
524 void EditorPanel::procParamsChanged (Thumbnail* thm, int whoChangedIt) {
526 if (whoChangedIt!=EDITOR)
527 tpc->profileChange (&openThm->getProcParams(), rtengine::EvProfileChangeNotification, "Profile Changed in Browser");
530 rtengine::IImage16* EditorPanel::processImage () {
532 rtengine::procparams::ProcParams pparams;
533 ipc->getParams (&pparams);
534 rtengine::ProcessingJob* job = rtengine::ProcessingJob::create (ipc->getInitialImage(), pparams);
535 int err = 0;
536 ProgressDialog<rtengine::IImage16*>* pdproc = new ProgressDialog<rtengine::IImage16*> (M("PROGRESSDLG_PROCESSING"));
537 rtengine::IImage16* img;
538 pdproc->setFunc (sigc::bind(sigc::ptr_fun(&rtengine::processImage), job, err, pdproc->getProgressListener()), &img);
539 pdproc->start ();
540 delete pdproc;
541 return img;
544 BatchQueueEntry* EditorPanel::createBatchQueueEntry () {
546 rtengine::procparams::ProcParams pparams;
547 ipc->getParams (&pparams);
548 rtengine::ProcessingJob* job = rtengine::ProcessingJob::create (ipc->getInitialImage(), pparams);
549 int prevh = options.maxThumbnailHeight;
550 int prevw = prevh;
551 guint8* prev = NULL;//(guint8*) previewHandler->getImagePreview (prevw, prevh);
552 return new BatchQueueEntry (job, pparams, openThm->getFileName(), prev, prevw, prevh, openThm);
555 int EditorPanel::saveImage (rtengine::IImage16* img, Glib::ustring& fname, SaveFormat sf, bool findNewNameIfNeeded) {
557 Glib::ustring fileName = Glib::ustring::compose ("%1.%2", fname, sf.format);
558 if (findNewNameIfNeeded) {
559 int tries = 1;
560 while (Glib::file_test (fileName, Glib::FILE_TEST_EXISTS) && tries<1000) {
561 fileName = Glib::ustring::compose("%1-%2.%3", fname, tries, sf.format);
562 tries++;
564 if (tries==1000)
565 return -1000;
568 ProgressDialog<int>* pdsave = new ProgressDialog<int> (M("PROGRESSDLG_SAVING"));
569 img->setSaveProgressListener (pdsave->getProgressListener());
571 int err;
572 if (sf.format=="tif")
573 pdsave->setFunc (sigc::bind(sigc::mem_fun(img, &rtengine::IImage16::saveAsTIFF), fileName, sf.tiffBits), &err);
574 else if (sf.format=="png")
575 pdsave->setFunc (sigc::bind(sigc::mem_fun(img, &rtengine::IImage16::saveAsPNG), fileName, sf.pngCompression, sf.pngBits), &err);
576 else if (sf.format=="jpg")
577 pdsave->setFunc (sigc::bind(sigc::mem_fun(img, &rtengine::IImage16::saveAsJPEG), fileName, sf.jpegQuality), &err);
578 pdsave->start ();
579 delete pdsave;
581 fname = fileName;
582 return err;
585 void EditorPanel::saveAsPressed () {
587 // obtaining short name without extension
588 saveAsDialog->setInitialFileName (removeExtension (Glib::path_get_basename (openThm->getFileName())));
589 saveAsDialog->run ();
590 Glib::ustring fname = saveAsDialog->getFileName ();
591 if (fname=="")
592 return;
594 SaveFormat sf = saveAsDialog->getFormat ();
595 if (getExtension (fname)!=sf.format)
596 fname = fname + "." + sf.format;
598 if (saveAsDialog->getImmediately ()) {
599 // check if it exists
600 if (Glib::file_test (fname, Glib::FILE_TEST_EXISTS)) {
601 Glib::ustring msg_ = Glib::ustring("<b>") + fname + ": " + M("MAIN_MSG_ALREADYEXISTS") + "\n" + M("MAIN_MSG_QOVERWRITE") + "</b>";
602 Gtk::MessageDialog msgd (*parent, msg_, true, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_YES_NO, true);
603 int response = msgd.run ();
604 if (response==Gtk::RESPONSE_NO)
605 return;
607 // save image
608 rtengine::IImage16* img = processImage ();
609 int err = 0;
610 if (img) {
611 fname = removeExtension (fname);
612 err = saveImage (img, fname, sf, false);
613 img->free ();
614 if (!err) {
615 openThm->imageDeveloped ();
616 // save processing parameters, if needed
617 if (sf.saveParams) {
618 rtengine::procparams::ProcParams pparams;
619 ipc->getParams (&pparams);
620 pparams.save (removeExtension (fname) + ".out.pp2");
624 if (!img || err) {
625 Glib::ustring msg_ = Glib::ustring("<b>") + fname + ": Error during image saving\n</b>";
626 Gtk::MessageDialog msgd (*parent, msg_, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
627 msgd.run ();
630 else {
631 BatchQueueEntry* bqe = createBatchQueueEntry ();
632 bqe->outFileName = fname;
633 bqe->saveFormat = saveAsDialog->getFormat ();
634 parent->addBatchQueueJob (bqe, saveAsDialog->getToHeadOfQueue ());
636 // ask parent to redraw file browser
637 // ... or does it automatically when the tab is switched to it
640 void EditorPanel::queueImgPressed () {
642 saveProfile ();
643 parent->addBatchQueueJob (createBatchQueueEntry ());
646 void EditorPanel::sendToGimpPressed () {
648 // develop image
649 rtengine::IImage16* img = processImage ();
650 if (img) {
651 // get file name base
652 Glib::ustring shortname = removeExtension (Glib::path_get_basename (openThm->getFileName()));
653 Glib::ustring dirname = Glib::get_tmp_dir ();
654 Glib::ustring filename = Glib::build_filename (dirname, shortname);
656 SaveFormat sf;
657 sf.format = "tif";
658 sf.tiffBits = 16;
659 int err = saveImage (img, filename, sf, true);
660 img->free ();
661 if (!err) {
662 bool success=false;
663 Glib::ustring cmdLine;
664 try {
665 // start gimp
666 if (options.editorToSendTo==1) {
667 #ifdef _WIN32
668 cmdLine = Glib::ustring("\"") + Glib::build_filename (Glib::build_filename(options.gimpDir,"bin"), "gimp-win-remote") + "\" gimp-2.4.exe" + " \"" + filename + "\"";
669 #else
670 cmdLine = Glib::ustring("gimp-remote ") + " \"" + filename + "\"";
671 #endif
672 try {
673 printf ("command line: |%s|\n", Glib::filename_from_utf8(cmdLine).c_str());
674 Glib::spawn_command_line_async (Glib::filename_from_utf8(cmdLine));
675 success = true;
677 catch (const Glib::SpawnError&) {
678 #ifdef _WIN32
679 int ver = 12;
680 while (!success && ver) {
681 cmdLine = Glib::ustring("\"") + Glib::build_filename (Glib::build_filename(options.gimpDir,"bin"), Glib::ustring::compose("gimp-2.%1.exe",ver)) + "\" \"" + filename + "\"";
682 ver--;
683 printf ("command line: |%s|\n", Glib::filename_from_utf8(cmdLine).c_str());
684 try {
685 Glib::spawn_command_line_async (Glib::filename_from_utf8(cmdLine));
686 success = true;
688 catch (const Glib::SpawnError&) {
689 success = false;
692 #else
693 cmdLine = Glib::ustring("gimp ") + " \"" + filename + "\"";
694 printf ("command line: |%s|\n", Glib::filename_from_utf8(cmdLine).c_str());
695 try {
696 Glib::spawn_command_line_async (Glib::filename_from_utf8(cmdLine));
697 success = true;
699 catch (const Glib::SpawnError&) {
700 success = false;
702 #endif
705 else if (options.editorToSendTo==2) {
706 cmdLine = Glib::ustring("\"") + Glib::build_filename(options.psDir,"Photoshop.exe") + "\" \"" + filename + "\"";
707 printf ("command line: |%s|\n", Glib::filename_from_utf8(cmdLine).c_str());
708 Glib::spawn_command_line_async (Glib::filename_from_utf8(cmdLine));
709 success = true;
711 else if (options.editorToSendTo==3) {
712 cmdLine = Glib::ustring("\"") + options.customEditorProg + "\" \"" + filename + "\"";
713 printf ("command line: |%s|\n", Glib::filename_from_utf8(cmdLine).c_str());
714 Glib::spawn_command_line_async (Glib::filename_from_utf8(cmdLine));
715 success = true;
718 catch (const Glib::SpawnError&) {
719 success = false;
721 if (!success) {
722 Gtk::MessageDialog* msgd = new Gtk::MessageDialog (*parent, M("MAIN_MSG_CANNOTSTARTEDITOR"), false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
723 msgd->set_secondary_text (M("MAIN_MSG_CANNOTSTARTEDITOR_SECONDARY"));
724 msgd->set_title (M("MAIN_BUTTON_SENDTOEDITOR"));
725 msgd->run ();
726 delete msgd;
732 void EditorPanel::saveOptions () {
734 options.historyPanelWidth = hpanedl->get_position ();
735 options.toolPanelWidth = vboxright->get_width ();
738 void EditorPanel::historyBeforeLineChanged (const rtengine::procparams::ProcParams& params) {
740 if (beforeIpc) {
741 ProcParams* pparams = beforeIpc->getParamsForUpdate (rtengine::EvProfileChanged);
742 *pparams = params;
743 beforeIpc->paramsUpdateReady ();
747 void EditorPanel::beforeAfterToggled () {
749 removeIfThere (beforeAfterBox, beforeBox, false);
750 removeIfThere (afterBox, afterLabel, false);
752 if (beforeIarea) {
753 if (beforeIpc)
754 beforeIpc->stopProcessing ();
755 iarea->setBeforeAfterViews (NULL, iarea);
756 delete beforeIarea;
757 beforeIarea = NULL;
758 if (beforeIpc)
759 beforeIpc->setPreviewImageListener (NULL);
760 delete beforePreviewHandler;
761 beforePreviewHandler = NULL;
762 if (beforeIpc)
763 rtengine::StagedImageProcessor::destroy (beforeIpc);
764 beforeIpc = NULL;
767 if (beforeAfter->get_active ()) {
769 beforeIarea = new ImageAreaPanel ();
771 beforeLabel = Gtk::manage (new Gtk::Label ());
772 beforeLabel->set_markup ("<b>Before:</b>");
773 beforeBox = Gtk::manage (new Gtk::VBox ());
774 beforeBox->pack_start (*beforeLabel, Gtk::PACK_SHRINK, 2);
775 beforeBox->pack_start (*beforeIarea);
777 afterLabel = Gtk::manage (new Gtk::Label ());
778 afterLabel->set_markup ("<b>After:</b>");
779 afterBox->pack_start (*afterLabel, Gtk::PACK_SHRINK, 2);
780 afterBox->reorder_child (*afterLabel, 0);
782 beforeAfterBox->pack_start (*beforeBox);
783 beforeAfterBox->reorder_child (*beforeBox, 0);
784 beforeAfterBox->show_all ();
786 beforePreviewHandler = new PreviewHandler ();
787 isrc->increaseRef ();
788 beforeIpc = rtengine::StagedImageProcessor::create (isrc);
789 beforeIpc->setPreviewScale (10);
790 beforeIpc->setPreviewImageListener (beforePreviewHandler);
791 beforeIarea->imageArea->setPreviewHandler (beforePreviewHandler);
792 beforeIarea->imageArea->setImProcCoordinator (beforeIpc);
794 iarea->setBeforeAfterViews (beforeIarea, iarea);
795 beforeIarea->setBeforeAfterViews (beforeIarea, iarea);
797 rtengine::procparams::ProcParams params;
798 if (history->getBeforeLineParams (params))
799 historyBeforeLineChanged (params);