"Fossies" - the Fresh Open Source Software Archive

Member "rawtherapee-5.7/rtgui/editorpanel.cc" (10 Sep 2019, 80493 Bytes) of package /linux/misc/rawtherapee-5.7.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "editorpanel.cc" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 5.6_vs_5.7.

    1 /*
    2  *  This file is part of RawTherapee.
    3  *
    4  *  Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
    5  *  Copyright (c) 2010 Oliver Duis <www.oliverduis.de>
    6  *
    7  *  RawTherapee is free software: you can redistribute it and/or modify
    8  *  it under the terms of the GNU General Public License as published by
    9  *  the Free Software Foundation, either version 3 of the License, or
   10  *  (at your option) any later version.
   11  *
   12  *  RawTherapee is distributed in the hope that it will be useful,
   13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   15  *  GNU General Public License for more details.
   16  *
   17  *  You should have received a copy of the GNU General Public License
   18  *  along with RawTherapee.  If not, see <https://www.gnu.org/licenses/>.
   19  */
   20 #include "editorpanel.h"
   21 
   22 #include <iostream>
   23 
   24 #include "../rtengine/imagesource.h"
   25 #include "../rtengine/iccstore.h"
   26 #include "soundman.h"
   27 #include "rtimage.h"
   28 #include "rtwindow.h"
   29 #include "guiutils.h"
   30 #include "popupbutton.h"
   31 #include "options.h"
   32 #include "progressconnector.h"
   33 #include "procparamchangers.h"
   34 #include "placesbrowser.h"
   35 
   36 using namespace rtengine::procparams;
   37 
   38 namespace
   39 {
   40 
   41 void setprogressStrUI(double val, const Glib::ustring str, MyProgressBar* pProgress)
   42 {
   43     if (!str.empty()) {
   44         pProgress->set_text(M(str));
   45     }
   46 
   47     if (val >= 0.0) {
   48         pProgress->set_fraction(val);
   49     }
   50 }
   51 
   52 
   53 bool find_default_monitor_profile (GdkWindow *rootwin, Glib::ustring &defprof, Glib::ustring &defprofname)
   54 {
   55 #ifdef WIN32
   56     HDC hDC = GetDC (nullptr);
   57 
   58     if (hDC != nullptr) {
   59         if (SetICMMode (hDC, ICM_ON)) {
   60             char profileName[MAX_PATH + 1];
   61             DWORD profileLength = MAX_PATH;
   62 
   63             if (GetICMProfileA (hDC, &profileLength, profileName)) {
   64                 defprof = Glib::ustring (profileName);
   65                 defprofname = Glib::path_get_basename (defprof);
   66                 size_t pos = defprofname.rfind (".");
   67 
   68                 if (pos != Glib::ustring::npos) {
   69                     defprofname = defprofname.substr (0, pos);
   70                 }
   71 
   72                 defprof = Glib::ustring ("file:") + defprof;
   73                 return true;
   74             }
   75 
   76             // might fail if e.g. the monitor has no profile
   77         }
   78 
   79         ReleaseDC (NULL, hDC);
   80     }
   81 
   82 #elif !defined(__APPLE__)
   83     // taken from geeqie (image.c) and adapted
   84     // Originally licensed as GPL v2+, with the following copyright:
   85     // * Copyright (C) 2006 John Ellis
   86     // * Copyright (C) 2008 - 2016 The Geeqie Team
   87     //
   88     guchar *prof = nullptr;
   89     gint proflen;
   90     GdkAtom type = GDK_NONE;
   91     gint format = 0;
   92 
   93     if (gdk_property_get (rootwin, gdk_atom_intern ("_ICC_PROFILE", FALSE), GDK_NONE, 0, 64 * 1024 * 1024, FALSE, &type, &format, &proflen, &prof) && proflen > 0) {
   94         cmsHPROFILE p = cmsOpenProfileFromMem (prof, proflen);
   95 
   96         if (p) {
   97             defprofname = "from GDK";
   98             defprof = Glib::build_filename (Options::rtdir, "GDK_ICC_PROFILE.icc");
   99 
  100             if (cmsSaveProfileToFile (p, defprof.c_str())) {
  101                 cmsCloseProfile (p);
  102 
  103                 if (prof) {
  104                     g_free (prof);
  105                 }
  106 
  107                 defprof = Glib::ustring ("file:") + defprof;
  108                 return true;
  109             }
  110         }
  111     }
  112 
  113     if (prof) {
  114         g_free (prof);
  115     }
  116 
  117 #endif
  118     return false;
  119 }
  120 
  121 
  122 }
  123 
  124 class EditorPanel::ColorManagementToolbar
  125 {
  126 private:
  127 #if !defined(__APPLE__) // monitor profile not supported on apple
  128     MyComboBoxText profileBox;
  129 #endif
  130     PopUpButton intentBox;
  131     Gtk::ToggleButton softProof;
  132     Gtk::ToggleButton spGamutCheck;
  133     sigc::connection profileConn, intentConn, softproofConn;
  134     Glib::ustring defprof;
  135 
  136     rtengine::StagedImageProcessor* const& processor;
  137 
  138 private:
  139 #if !defined(__APPLE__) // monitor profile not supported on apple
  140     void prepareProfileBox ()
  141     {
  142         profileBox.setPreferredWidth (70, 200);
  143         setExpandAlignProperties (&profileBox, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_FILL);
  144 
  145         profileBox.append (M ("PREFERENCES_PROFILE_NONE"));
  146         Glib::ustring defprofname;
  147 
  148         if (find_default_monitor_profile (profileBox.get_root_window()->gobj(), defprof, defprofname)) {
  149             profileBox.append (M ("MONITOR_PROFILE_SYSTEM") + " (" + defprofname + ")");
  150 
  151             if (options.rtSettings.autoMonitorProfile) {
  152                 rtengine::ICCStore::getInstance()->setDefaultMonitorProfileName (defprof);
  153                 profileBox.set_active (1);
  154             } else {
  155                 profileBox.set_active (0);
  156             }
  157         } else {
  158             profileBox.set_active (0);
  159         }
  160 
  161         const std::vector<Glib::ustring> profiles = rtengine::ICCStore::getInstance()->getProfiles (rtengine::ICCStore::ProfileType::MONITOR);
  162 
  163         for (const auto profile : profiles) {
  164             profileBox.append (profile);
  165         }
  166 
  167         profileBox.set_tooltip_text (profileBox.get_active_text ());
  168     }
  169 #endif
  170 
  171     void prepareIntentBox ()
  172     {
  173         // same order as the enum
  174         intentBox.addEntry ("intent-perceptual.png", M ("PREFERENCES_INTENT_PERCEPTUAL"));
  175         intentBox.addEntry ("intent-relative.png", M ("PREFERENCES_INTENT_RELATIVE"));
  176         intentBox.addEntry ("intent-absolute.png", M ("PREFERENCES_INTENT_ABSOLUTE"));
  177         setExpandAlignProperties (intentBox.buttonGroup, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_FILL);
  178 
  179         intentBox.setSelected (1);
  180         intentBox.show ();
  181     }
  182 
  183     void prepareSoftProofingBox ()
  184     {
  185         Gtk::Image *softProofImage = Gtk::manage (new RTImage ("gamut-softproof.png"));
  186         softProofImage->set_padding (0, 0);
  187         softProof.add (*softProofImage);
  188         softProof.set_relief (Gtk::RELIEF_NONE);
  189         softProof.set_tooltip_markup (M ("SOFTPROOF_TOOLTIP"));
  190 
  191         softProof.set_active (false);
  192         softProof.show ();
  193 
  194         Gtk::Image *spGamutCheckImage = Gtk::manage (new RTImage ("gamut-warning.png"));
  195         spGamutCheckImage->set_padding (0, 0);
  196         spGamutCheck.add (*spGamutCheckImage);
  197         spGamutCheck.set_relief (Gtk::RELIEF_NONE);
  198         spGamutCheck.set_tooltip_markup (M ("SOFTPROOF_GAMUTCHECK_TOOLTIP"));
  199 
  200         spGamutCheck.set_active (false);
  201         spGamutCheck.set_sensitive (true);
  202         spGamutCheck.show ();
  203     }
  204 
  205 #if !defined(__APPLE__)
  206     void profileBoxChanged ()
  207     {
  208         updateParameters ();
  209     }
  210 #endif
  211 
  212     void intentBoxChanged (int)
  213     {
  214         updateParameters ();
  215     }
  216 
  217     void softProofToggled ()
  218     {
  219         updateSoftProofParameters ();
  220     }
  221 
  222     void spGamutCheckToggled ()
  223     {
  224         updateSoftProofParameters ();
  225     }
  226 
  227     void updateParameters (bool noEvent = false)
  228     {
  229 #if !defined(__APPLE__) // monitor profile not supported on apple
  230         ConnectionBlocker profileBlocker (profileConn);
  231 #endif
  232         ConnectionBlocker intentBlocker (intentConn);
  233 
  234         Glib::ustring profile;
  235 
  236 #if !defined(__APPLE__) // monitor profile not supported on apple
  237 
  238         if (!defprof.empty() && profileBox.get_active_row_number () == 1) {
  239             profile = defprof;
  240 
  241             if (profile.empty ()) {
  242                 profile = options.rtSettings.monitorProfile;
  243             }
  244 
  245             if (profile.empty ()) {
  246                 profile = "sRGB IEC61966-2.1";
  247             }
  248         } else if (profileBox.get_active_row_number () > 0) {
  249             profile = profileBox.get_active_text ();
  250         }
  251 
  252 #else
  253         profile = options.rtSettings.srgb;
  254 #endif
  255 
  256 #if !defined(__APPLE__) // monitor profile not supported on apple
  257 
  258         if (profileBox.get_active_row_number () == 0) {
  259 
  260             profile.clear ();
  261 
  262             intentBox.set_sensitive (false);
  263             intentBox.setSelected (1);
  264             softProof.set_sensitive (false);
  265             spGamutCheck.set_sensitive (false);
  266 
  267             profileBox.set_tooltip_text ("");
  268 
  269         } else {
  270             const uint8_t supportedIntents = rtengine::ICCStore::getInstance()->getProofIntents (profile);
  271             const bool supportsRelativeColorimetric = supportedIntents & 1 << INTENT_RELATIVE_COLORIMETRIC;
  272             const bool supportsPerceptual = supportedIntents & 1 << INTENT_PERCEPTUAL;
  273             const bool supportsAbsoluteColorimetric = supportedIntents & 1 << INTENT_ABSOLUTE_COLORIMETRIC;
  274 
  275             if (supportsPerceptual || supportsRelativeColorimetric || supportsAbsoluteColorimetric) {
  276                 intentBox.set_sensitive (true);
  277                 intentBox.setItemSensitivity (0, supportsPerceptual);
  278                 intentBox.setItemSensitivity (1, supportsRelativeColorimetric);
  279                 intentBox.setItemSensitivity (2, supportsAbsoluteColorimetric);
  280                 softProof.set_sensitive (true);
  281                 spGamutCheck.set_sensitive (true);
  282             } else {
  283                 intentBox.setItemSensitivity (0, true);
  284                 intentBox.setItemSensitivity (1, true);
  285                 intentBox.setItemSensitivity (2, true);
  286                 intentBox.set_sensitive (false);
  287                 intentBox.setSelected (1);
  288                 softProof.set_sensitive (false);
  289                 spGamutCheck.set_sensitive (true);
  290             }
  291 
  292             profileBox.set_tooltip_text (profileBox.get_active_text ());
  293         }
  294 
  295 #endif
  296         rtengine::RenderingIntent intent;
  297 
  298         switch (intentBox.getSelected ()) {
  299             default:
  300             case 0:
  301                 intent = rtengine::RI_PERCEPTUAL;
  302                 break;
  303 
  304             case 1:
  305                 intent = rtengine::RI_RELATIVE;
  306                 break;
  307 
  308             case 2:
  309                 intent = rtengine::RI_ABSOLUTE;
  310                 break;
  311         }
  312 
  313         if (!processor) {
  314             return;
  315         }
  316 
  317         if (!noEvent) {
  318             processor->beginUpdateParams ();
  319         }
  320 
  321         processor->setMonitorProfile (profile, intent);
  322         processor->setSoftProofing (softProof.get_sensitive() && softProof.get_active(), spGamutCheck.get_sensitive() && spGamutCheck.get_active());
  323 
  324         if (!noEvent) {
  325             processor->endUpdateParams (rtengine::EvMonitorTransform);
  326         }
  327     }
  328 
  329     void updateSoftProofParameters (bool noEvent = false)
  330     {
  331 #if !defined(__APPLE__) // monitor profile not supported on apple
  332         softProof.set_sensitive (profileBox.get_active_row_number () > 0);
  333         spGamutCheck.set_sensitive(profileBox.get_active_row_number () > 0);
  334 #endif
  335 
  336 
  337 #if !defined(__APPLE__) // monitor profile not supported on apple
  338 
  339         if (profileBox.get_active_row_number () > 0) {
  340 #endif
  341 
  342             if (processor) {
  343                 if (!noEvent) {
  344                     processor->beginUpdateParams ();
  345                 }
  346 
  347                 processor->setSoftProofing (softProof.get_sensitive() && softProof.get_active(), spGamutCheck.get_active());
  348 
  349                 if (!noEvent) {
  350                     processor->endUpdateParams (rtengine::EvMonitorTransform);
  351                 }
  352             }
  353 
  354 #if !defined(__APPLE__) // monitor profile not supported on apple
  355         }
  356 
  357 #endif
  358     }
  359 
  360 public:
  361     explicit ColorManagementToolbar (rtengine::StagedImageProcessor* const& ipc) :
  362         intentBox (Glib::ustring (), true),
  363         processor (ipc)
  364     {
  365 #if !defined(__APPLE__) // monitor profile not supported on apple
  366         prepareProfileBox ();
  367 #endif
  368         prepareIntentBox ();
  369         prepareSoftProofingBox ();
  370 
  371         reset ();
  372 
  373         softproofConn = softProof.signal_toggled().connect (sigc::mem_fun (this, &ColorManagementToolbar::softProofToggled));
  374         spGamutCheck.signal_toggled().connect (sigc::mem_fun (this, &ColorManagementToolbar::spGamutCheckToggled));
  375 #if !defined(__APPLE__) // monitor profile not supported on apple
  376         profileConn = profileBox.signal_changed ().connect (sigc::mem_fun (this, &ColorManagementToolbar::profileBoxChanged));
  377 #endif
  378         intentConn = intentBox.signal_changed ().connect (sigc::mem_fun (this, &ColorManagementToolbar::intentBoxChanged));
  379     }
  380 
  381     void pack_right_in (Gtk::Grid* grid)
  382     {
  383 #if !defined(__APPLE__) // monitor profile not supported on apple
  384         grid->attach_next_to (profileBox, Gtk::POS_RIGHT, 1, 1);
  385 #endif
  386         grid->attach_next_to (*intentBox.buttonGroup, Gtk::POS_RIGHT, 1, 1);
  387         grid->attach_next_to (softProof, Gtk::POS_RIGHT, 1, 1);
  388         grid->attach_next_to (spGamutCheck, Gtk::POS_RIGHT, 1, 1);
  389     }
  390 
  391     void updateProcessor()
  392     {
  393         if (processor) {
  394             updateParameters (true);
  395         }
  396     }
  397 
  398     void reset ()
  399     {
  400         ConnectionBlocker intentBlocker (intentConn);
  401 #if !defined(__APPLE__) // monitor profile not supported on apple
  402         ConnectionBlocker profileBlocker (profileConn);
  403 
  404         if (!defprof.empty() && options.rtSettings.autoMonitorProfile) {
  405             profileBox.set_active (1);
  406         } else {
  407             setActiveTextOrIndex (profileBox, options.rtSettings.monitorProfile, 0);
  408         }
  409 
  410 #endif
  411 
  412         switch (options.rtSettings.monitorIntent) {
  413             default:
  414             case rtengine::RI_PERCEPTUAL:
  415                 intentBox.setSelected (0);
  416                 break;
  417 
  418             case rtengine::RI_RELATIVE:
  419                 intentBox.setSelected (1);
  420                 break;
  421 
  422             case rtengine::RI_ABSOLUTE:
  423                 intentBox.setSelected (2);
  424                 break;
  425         }
  426 
  427         updateParameters ();
  428     }
  429 
  430     void updateHistogram()
  431     {
  432       updateParameters();
  433     }
  434 
  435 
  436     void defaultMonitorProfileChanged (const Glib::ustring &profile_name, bool auto_monitor_profile)
  437     {
  438         ConnectionBlocker profileBlocker (profileConn);
  439 
  440         if (auto_monitor_profile && !defprof.empty()) {
  441             rtengine::ICCStore::getInstance()->setDefaultMonitorProfileName (defprof);
  442 #ifndef __APPLE__
  443             profileBox.set_active (1);
  444 #endif
  445         } else {
  446             rtengine::ICCStore::getInstance()->setDefaultMonitorProfileName (profile_name);
  447 #ifndef __APPLE__
  448             setActiveTextOrIndex (profileBox, profile_name, 0);
  449 #endif
  450         }
  451     }
  452 
  453 };
  454 
  455 EditorPanel::EditorPanel (FilePanel* filePanel)
  456     : catalogPane (nullptr), realized (false), tbBeforeLock (nullptr), iHistoryShow (nullptr), iHistoryHide (nullptr),
  457       iTopPanel_1_Show (nullptr), iTopPanel_1_Hide (nullptr), iRightPanel_1_Show (nullptr), iRightPanel_1_Hide (nullptr),
  458       iBeforeLockON (nullptr), iBeforeLockOFF (nullptr), previewHandler (nullptr), beforePreviewHandler (nullptr),
  459       beforeIarea (nullptr), beforeBox (nullptr), afterBox (nullptr), beforeLabel (nullptr), afterLabel (nullptr),
  460       beforeHeaderBox (nullptr), afterHeaderBox (nullptr), parent (nullptr), parentWindow (nullptr), openThm (nullptr),
  461       selectedFrame(0), isrc (nullptr), ipc (nullptr), beforeIpc (nullptr), err (0), isProcessing (false)
  462 {
  463 
  464     epih = new EditorPanelIdleHelper;
  465     epih->epanel = this;
  466     epih->destroyed = false;
  467     epih->pending = 0;
  468     //rtengine::befaf=true;
  469     processingStartedTime = 0;
  470     firstProcessingDone = false;
  471 
  472     // construct toolpanelcoordinator
  473     tpc = new ToolPanelCoordinator ();
  474 
  475     // build GUI
  476 
  477     // build left side panel
  478     leftbox = new Gtk::Paned (Gtk::ORIENTATION_VERTICAL);
  479 
  480     // make a subbox to allow resizing of the histogram (if it's on the left)
  481     leftsubbox = new Gtk::Box (Gtk::ORIENTATION_VERTICAL);
  482     leftsubbox->set_size_request (230, 250);
  483 
  484     histogramPanel = nullptr;
  485 
  486     profilep = Gtk::manage (new ProfilePanel ());
  487     ppframe = Gtk::manage(new Gtk::Frame());
  488     ppframe->set_name ("ProfilePanel");
  489     ppframe->add (*profilep);
  490     ppframe->set_label (M ("PROFILEPANEL_LABEL"));
  491     //leftsubbox->pack_start (*ppframe, Gtk::PACK_SHRINK, 4);
  492 
  493     navigator = Gtk::manage (new Navigator ());
  494     navigator->previewWindow->set_size_request (-1, 150 * RTScalable::getScale());
  495     leftsubbox->pack_start (*navigator, Gtk::PACK_SHRINK, 2);
  496 
  497     history = Gtk::manage (new History ());
  498     leftsubbox->pack_start (*history);
  499 
  500     leftsubbox->show_all ();
  501 
  502     leftbox->pack2 (*leftsubbox, true, true);
  503     leftbox->show_all ();
  504 
  505     // build the middle of the screen
  506     Gtk::Box* editbox = Gtk::manage (new Gtk::Box (Gtk::ORIENTATION_VERTICAL));
  507 
  508     info = Gtk::manage (new Gtk::ToggleButton ());
  509     Gtk::Image* infoimg = Gtk::manage (new RTImage ("info.png"));
  510     info->add (*infoimg);
  511     info->set_relief (Gtk::RELIEF_NONE);
  512     info->set_tooltip_markup (M ("MAIN_TOOLTIP_QINFO"));
  513 
  514     beforeAfter = Gtk::manage (new Gtk::ToggleButton ());
  515     Gtk::Image* beforeAfterIcon = Gtk::manage (new RTImage ("beforeafter.png"));
  516     beforeAfter->add (*beforeAfterIcon);
  517     beforeAfter->set_relief (Gtk::RELIEF_NONE);
  518     beforeAfter->set_tooltip_markup (M ("MAIN_TOOLTIP_TOGGLE"));
  519 
  520     iBeforeLockON = new RTImage ("padlock-locked-small.png");
  521     iBeforeLockOFF = new RTImage ("padlock-unlocked-small.png");
  522 
  523     Gtk::VSeparator* vsept = Gtk::manage (new Gtk::VSeparator ());
  524     Gtk::VSeparator* vsepz = Gtk::manage (new Gtk::VSeparator ());
  525     Gtk::VSeparator* vsepi = Gtk::manage (new Gtk::VSeparator ());
  526     Gtk::VSeparator* vseph = Gtk::manage (new Gtk::VSeparator ());
  527 
  528     hidehp = Gtk::manage (new Gtk::ToggleButton ());
  529 
  530     iHistoryShow = new RTImage ("panel-to-right.png");
  531     iHistoryHide = new RTImage ("panel-to-left.png");
  532 
  533     hidehp->set_relief (Gtk::RELIEF_NONE);
  534     hidehp->set_active (options.showHistory);
  535     hidehp->set_tooltip_markup (M ("MAIN_TOOLTIP_HIDEHP"));
  536 
  537     if (options.showHistory) {
  538         hidehp->set_image (*iHistoryHide);
  539     } else {
  540         hidehp->set_image (*iHistoryShow);
  541     }
  542 
  543     tbTopPanel_1 = nullptr;
  544 
  545     if (!simpleEditor && filePanel) {
  546         tbTopPanel_1 = new Gtk::ToggleButton ();
  547         iTopPanel_1_Show = new RTImage ("panel-to-bottom.png");
  548         iTopPanel_1_Hide = new RTImage ("panel-to-top.png");
  549         tbTopPanel_1->set_relief (Gtk::RELIEF_NONE);
  550         tbTopPanel_1->set_active (true);
  551         tbTopPanel_1->set_tooltip_markup (M ("MAIN_TOOLTIP_SHOWHIDETP1"));
  552         tbTopPanel_1->set_image (*iTopPanel_1_Hide);
  553     }
  554 
  555     Gtk::VSeparator* vsepcl = Gtk::manage (new Gtk::VSeparator ());
  556     Gtk::VSeparator* vsepz2 = Gtk::manage (new Gtk::VSeparator ());
  557     Gtk::VSeparator* vsepz3 = Gtk::manage (new Gtk::VSeparator ());
  558     Gtk::VSeparator* vsepz4 = Gtk::manage (new Gtk::VSeparator ());
  559 
  560     Gtk::VSeparator* vsep1 = Gtk::manage (new Gtk::VSeparator ());
  561     Gtk::VSeparator* vsep2 = Gtk::manage (new Gtk::VSeparator ());
  562 
  563     // Histogram profile toggle controls
  564     toggleHistogramProfile = Gtk::manage (new Gtk::ToggleButton ());
  565     Gtk::Image* histProfImg = Gtk::manage (new RTImage ("gamut-hist.png"));
  566     toggleHistogramProfile->add (*histProfImg);
  567     toggleHistogramProfile->set_relief (Gtk::RELIEF_NONE);
  568     toggleHistogramProfile->set_active (options.rtSettings.HistogramWorking);
  569     toggleHistogramProfile->set_tooltip_markup ( (M ("PREFERENCES_HISTOGRAM_TOOLTIP")));
  570 
  571     Gtk::VSeparator* vsep3 = Gtk::manage (new Gtk::VSeparator ());
  572 
  573     iareapanel = new ImageAreaPanel ();
  574     tpc->setEditProvider (iareapanel->imageArea);
  575     tpc->getToolBar()->setLockablePickerToolListener (iareapanel->imageArea);
  576 
  577     Gtk::Box* toolBarPanel = Gtk::manage (new Gtk::Box (Gtk::ORIENTATION_HORIZONTAL));
  578     toolBarPanel->set_name ("EditorTopPanel");
  579     toolBarPanel->pack_start (*hidehp, Gtk::PACK_SHRINK, 1);
  580     toolBarPanel->pack_start (*vseph, Gtk::PACK_SHRINK, 2);
  581     toolBarPanel->pack_start (*info, Gtk::PACK_SHRINK, 1);
  582     toolBarPanel->pack_start (*beforeAfter, Gtk::PACK_SHRINK, 1);
  583     toolBarPanel->pack_start (*vsepi, Gtk::PACK_SHRINK, 2);
  584     toolBarPanel->pack_start (*tpc->getToolBar(), Gtk::PACK_SHRINK, 1);
  585     toolBarPanel->pack_start (*vsept, Gtk::PACK_SHRINK, 2);
  586 
  587     if (tbTopPanel_1) {
  588         Gtk::VSeparator* vsep = Gtk::manage (new Gtk::VSeparator ());
  589         toolBarPanel->pack_end   (*tbTopPanel_1, Gtk::PACK_SHRINK, 1);
  590         toolBarPanel->pack_end   (*vsep, Gtk::PACK_SHRINK, 2);
  591     }
  592 
  593     toolBarPanel->pack_end   (*tpc->coarse, Gtk::PACK_SHRINK, 2);
  594     toolBarPanel->pack_end   (*vsepcl, Gtk::PACK_SHRINK, 2);
  595     // Histogram profile toggle
  596     toolBarPanel->pack_end (*toggleHistogramProfile, Gtk::PACK_SHRINK, 1);
  597     toolBarPanel->pack_end (*vsep3, Gtk::PACK_SHRINK, 2);
  598 
  599     toolBarPanel->pack_end   (*iareapanel->imageArea->indClippedPanel, Gtk::PACK_SHRINK, 0);
  600     toolBarPanel->pack_end   (*vsepz, Gtk::PACK_SHRINK, 2);
  601     toolBarPanel->pack_end   (*iareapanel->imageArea->previewModePanel, Gtk::PACK_SHRINK, 0);
  602     toolBarPanel->pack_end   (*vsepz4, Gtk::PACK_SHRINK, 2);
  603 
  604     afterBox = Gtk::manage (new Gtk::Box (Gtk::ORIENTATION_VERTICAL));
  605     afterBox->pack_start (*iareapanel);
  606 
  607     beforeAfterBox = Gtk::manage (new Gtk::Box (Gtk::ORIENTATION_HORIZONTAL));
  608     beforeAfterBox->set_name ("BeforeAfterContainer");
  609     beforeAfterBox->pack_start (*afterBox);
  610 
  611     MyScrolledToolbar *stb1 = Gtk::manage(new MyScrolledToolbar());
  612     stb1->set_name("EditorToolbarTop");
  613     stb1->add(*toolBarPanel);
  614     editbox->pack_start (*stb1, Gtk::PACK_SHRINK, 2);
  615     editbox->pack_start (*beforeAfterBox);
  616 
  617     // build right side panel
  618     vboxright = new Gtk::Paned (Gtk::ORIENTATION_VERTICAL);
  619 
  620     vsubboxright = new Gtk::Box (Gtk::ORIENTATION_VERTICAL, 0);
  621     vsubboxright->set_size_request (300, 250);
  622 
  623     vsubboxright->pack_start (*ppframe, Gtk::PACK_SHRINK, 2);
  624     // main notebook
  625     vsubboxright->pack_start (*tpc->toolPanelNotebook);
  626 
  627     vboxright->pack2 (*vsubboxright, true, true);
  628 
  629     // Save buttons
  630     Gtk::Grid *iops = Gtk::manage(new Gtk::Grid());
  631     iops->set_name ("IopsPanel");
  632     iops->set_orientation (Gtk::ORIENTATION_HORIZONTAL);
  633     iops->set_row_spacing (2);
  634     iops->set_column_spacing (2);
  635 
  636     Gtk::Image *saveButtonImage =  Gtk::manage (new RTImage ("save.png"));
  637     saveimgas = Gtk::manage (new Gtk::Button ());
  638     saveimgas->set_relief(Gtk::RELIEF_NONE);
  639     saveimgas->add (*saveButtonImage);
  640     saveimgas->set_tooltip_markup (M ("MAIN_BUTTON_SAVE_TOOLTIP"));
  641     setExpandAlignProperties (saveimgas, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_FILL);
  642 
  643     Gtk::Image *queueButtonImage = Gtk::manage (new RTImage ("gears.png"));
  644     queueimg = Gtk::manage (new Gtk::Button ());
  645     queueimg->set_relief(Gtk::RELIEF_NONE);
  646     queueimg->add (*queueButtonImage);
  647     queueimg->set_tooltip_markup (M ("MAIN_BUTTON_PUTTOQUEUE_TOOLTIP"));
  648     setExpandAlignProperties (queueimg, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_FILL);
  649 
  650     Gtk::Image *sendToEditorButtonImage = Gtk::manage (new RTImage ("palette-brush.png"));
  651     sendtogimp = Gtk::manage (new Gtk::Button ());
  652     sendtogimp->set_relief(Gtk::RELIEF_NONE);
  653     sendtogimp->add (*sendToEditorButtonImage);
  654     sendtogimp->set_tooltip_markup (M ("MAIN_BUTTON_SENDTOEDITOR_TOOLTIP"));
  655     setExpandAlignProperties (sendtogimp, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_FILL);
  656 
  657     // Status box
  658     progressLabel = Gtk::manage (new MyProgressBar (300));
  659     progressLabel->set_show_text (true);
  660     setExpandAlignProperties (progressLabel, true, false, Gtk::ALIGN_START, Gtk::ALIGN_FILL);
  661     progressLabel->set_fraction (0.0);
  662 
  663     // tbRightPanel_1
  664     tbRightPanel_1 = Gtk::manage(new Gtk::ToggleButton());
  665     iRightPanel_1_Show = new RTImage ("panel-to-left.png");
  666     iRightPanel_1_Hide = new RTImage ("panel-to-right.png");
  667     tbRightPanel_1->set_relief (Gtk::RELIEF_NONE);
  668     tbRightPanel_1->set_active (true);
  669     tbRightPanel_1->set_tooltip_markup (M ("MAIN_TOOLTIP_SHOWHIDERP1"));
  670     tbRightPanel_1->set_image (*iRightPanel_1_Hide);
  671     setExpandAlignProperties (tbRightPanel_1, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_FILL);
  672 
  673     // ShowHideSidePanels
  674     tbShowHideSidePanels = Gtk::manage(new Gtk::ToggleButton());
  675     iShowHideSidePanels = new RTImage ("crossed-arrows-out.png");
  676     iShowHideSidePanels_exit = new RTImage ("crossed-arrows-in.png");
  677     tbShowHideSidePanels->set_relief (Gtk::RELIEF_NONE);
  678     tbShowHideSidePanels->set_active (false);
  679     tbShowHideSidePanels->set_tooltip_markup (M ("MAIN_BUTTON_SHOWHIDESIDEPANELS_TOOLTIP"));
  680     tbShowHideSidePanels->set_image (*iShowHideSidePanels);
  681     setExpandAlignProperties (tbShowHideSidePanels, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_FILL);
  682 
  683     navPrev = navNext = navSync = nullptr;
  684 
  685     if (!simpleEditor && !options.tabbedUI) {
  686         // Navigation buttons
  687         Gtk::Image *navPrevImage = Gtk::manage (new RTImage ("arrow2-left.png"));
  688         navPrevImage->set_padding (0, 0);
  689         navPrev = Gtk::manage (new Gtk::Button ());
  690         navPrev->add (*navPrevImage);
  691         navPrev->set_relief (Gtk::RELIEF_NONE);
  692         navPrev->set_tooltip_markup (M ("MAIN_BUTTON_NAVPREV_TOOLTIP"));
  693         setExpandAlignProperties (navPrev, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_FILL);
  694 
  695         Gtk::Image *navNextImage = Gtk::manage (new RTImage ("arrow2-right.png"));
  696         navNextImage->set_padding (0, 0);
  697         navNext = Gtk::manage (new Gtk::Button ());
  698         navNext->add (*navNextImage);
  699         navNext->set_relief (Gtk::RELIEF_NONE);
  700         navNext->set_tooltip_markup (M ("MAIN_BUTTON_NAVNEXT_TOOLTIP"));
  701         setExpandAlignProperties (navNext, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_FILL);
  702 
  703         Gtk::Image *navSyncImage = Gtk::manage (new RTImage ("arrow-updown.png"));
  704         navSyncImage->set_padding (0, 0);
  705         navSync = Gtk::manage (new Gtk::Button ());
  706         navSync->add (*navSyncImage);
  707         navSync->set_relief (Gtk::RELIEF_NONE);
  708         navSync->set_tooltip_markup (M ("MAIN_BUTTON_NAVSYNC_TOOLTIP"));
  709         setExpandAlignProperties (navSync, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_FILL);
  710     }
  711 
  712     // ==================  PACKING THE BOTTOM WIDGETS =================
  713 
  714     // Adding widgets from center to the left, on the left side (using Gtk::POS_LEFT)
  715     iops->attach_next_to (*vsep2, Gtk::POS_LEFT, 1, 1);
  716     iops->attach_next_to (*progressLabel, Gtk::POS_LEFT, 1, 1);
  717     iops->attach_next_to (*vsep1, Gtk::POS_LEFT, 1, 1);
  718 
  719     if (!gimpPlugin) {
  720         iops->attach_next_to (*sendtogimp, Gtk::POS_LEFT, 1, 1);
  721     }
  722 
  723     if (!gimpPlugin && !simpleEditor) {
  724         iops->attach_next_to (*queueimg, Gtk::POS_LEFT, 1, 1);
  725     }
  726 
  727     if (!gimpPlugin) {
  728         iops->attach_next_to (*saveimgas, Gtk::POS_LEFT, 1, 1);
  729     }
  730 
  731 
  732     // Color management toolbar
  733     colorMgmtToolBar.reset (new ColorManagementToolbar (ipc));
  734     colorMgmtToolBar->pack_right_in (iops);
  735 
  736     if (!simpleEditor && !options.tabbedUI) {
  737         Gtk::VSeparator* vsep3 = Gtk::manage (new Gtk::VSeparator ());
  738         iops->attach_next_to (*vsep3, Gtk::POS_RIGHT, 1, 1);
  739         iops->attach_next_to (*navPrev, Gtk::POS_RIGHT, 1, 1);
  740         iops->attach_next_to (*navSync, Gtk::POS_RIGHT, 1, 1);
  741         iops->attach_next_to (*navNext, Gtk::POS_RIGHT, 1, 1);
  742     }
  743 
  744     iops->attach_next_to (*vsepz2, Gtk::POS_RIGHT, 1, 1);
  745     iops->attach_next_to (*iareapanel->imageArea->zoomPanel, Gtk::POS_RIGHT, 1, 1);
  746     iops->attach_next_to (*vsepz3, Gtk::POS_RIGHT, 1, 1);
  747     iops->attach_next_to (*tbShowHideSidePanels, Gtk::POS_RIGHT, 1, 1);
  748     iops->attach_next_to (*tbRightPanel_1, Gtk::POS_RIGHT, 1, 1);
  749 
  750     MyScrolledToolbar *stb2 = Gtk::manage(new MyScrolledToolbar());
  751     stb2->set_name("EditorToolbarBottom");
  752     stb2->add(*iops);
  753 
  754     editbox->pack_start (*stb2, Gtk::PACK_SHRINK, 0);
  755     editbox->show_all ();
  756 
  757     // build screen
  758     hpanedl = Gtk::manage (new Gtk::Paned (Gtk::ORIENTATION_HORIZONTAL));
  759     hpanedl->set_name ("EditorLeftPaned");
  760     hpanedr = Gtk::manage (new Gtk::Paned (Gtk::ORIENTATION_HORIZONTAL));
  761     hpanedr->set_name ("EditorRightPaned");
  762     leftbox->reference ();
  763     vboxright->reference ();
  764 
  765     if (options.showHistory) {
  766         hpanedl->pack1 (*leftbox, false, false);
  767         hpanedl->set_position (options.historyPanelWidth);
  768     }
  769 
  770     Gtk::Paned *viewpaned = Gtk::manage (new Gtk::Paned (Gtk::ORIENTATION_VERTICAL));
  771     fPanel = filePanel;
  772 
  773     if (filePanel) {
  774         catalogPane = new Gtk::Paned();
  775         viewpaned->pack1 (*catalogPane, false, true);
  776     }
  777 
  778     viewpaned->pack2 (*editbox, true, true);
  779 
  780     hpanedl->pack2 (*viewpaned, true, true);
  781 
  782     hpanedr->pack1 (*hpanedl, true, false);
  783     hpanedr->pack2 (*vboxright, false, false);
  784     hpanedl->signal_button_release_event().connect_notify ( sigc::mem_fun (*this, &EditorPanel::leftPaneButtonReleased) );
  785     hpanedr->signal_button_release_event().connect_notify ( sigc::mem_fun (*this, &EditorPanel::rightPaneButtonReleased) );
  786 
  787     pack_start (*hpanedr);
  788 
  789     updateHistogramPosition (0, options.histogramPosition);
  790 
  791     show_all ();
  792     /*
  793         // save as dialog
  794         if (Glib::file_test (options.lastSaveAsPath, Glib::FILE_TEST_IS_DIR))
  795             saveAsDialog = new SaveAsDialog (options.lastSaveAsPath);
  796         else
  797             saveAsDialog = new SaveAsDialog (safe_get_user_picture_dir());
  798 
  799         saveAsDialog->set_default_size (options.saveAsDialogWidth, options.saveAsDialogHeight);
  800     */
  801     // connect listeners
  802     profilep->setProfileChangeListener (tpc);
  803     history->setProfileChangeListener (tpc);
  804     history->setHistoryBeforeLineListener (this);
  805     tpc->addPParamsChangeListener (profilep);
  806     tpc->addPParamsChangeListener (history);
  807     tpc->addPParamsChangeListener (this);
  808     iareapanel->imageArea->setCropGUIListener (tpc->getCropGUIListener());
  809     iareapanel->imageArea->setPointerMotionListener (navigator);
  810     iareapanel->imageArea->setImageAreaToolListener (tpc);
  811 
  812     // initialize components
  813     info->set_active (options.showInfo);
  814     tpc->readOptions ();
  815 
  816     // connect event handlers
  817     info->signal_toggled().connect ( sigc::mem_fun (*this, &EditorPanel::info_toggled) );
  818     beforeAfter->signal_toggled().connect ( sigc::mem_fun (*this, &EditorPanel::beforeAfterToggled) );
  819     hidehp->signal_toggled().connect ( sigc::mem_fun (*this, &EditorPanel::hideHistoryActivated) );
  820     tbRightPanel_1->signal_toggled().connect ( sigc::mem_fun (*this, &EditorPanel::tbRightPanel_1_toggled) );
  821     saveimgas->signal_pressed().connect ( sigc::mem_fun (*this, &EditorPanel::saveAsPressed) );
  822     queueimg->signal_pressed().connect ( sigc::mem_fun (*this, &EditorPanel::queueImgPressed) );
  823     sendtogimp->signal_pressed().connect ( sigc::mem_fun (*this, &EditorPanel::sendToGimpPressed) );
  824     toggleHistogramProfile->signal_toggled().connect( sigc::mem_fun (*this, &EditorPanel::histogramProfile_toggled) );
  825 
  826     if (navPrev) {
  827         navPrev->signal_pressed().connect ( sigc::mem_fun (*this, &EditorPanel::openPreviousEditorImage) );
  828     }
  829 
  830     if (navNext) {
  831         navNext->signal_pressed().connect ( sigc::mem_fun (*this, &EditorPanel::openNextEditorImage) );
  832     }
  833 
  834     if (navSync) {
  835         navSync->signal_pressed().connect ( sigc::mem_fun (*this, &EditorPanel::syncFileBrowser) );
  836     }
  837 
  838     ShowHideSidePanelsconn = tbShowHideSidePanels->signal_toggled().connect ( sigc::mem_fun (*this, &EditorPanel::toggleSidePanels), true);
  839 
  840     if (tbTopPanel_1) {
  841         tbTopPanel_1->signal_toggled().connect ( sigc::mem_fun (*this, &EditorPanel::tbTopPanel_1_toggled) );
  842     }
  843 
  844 }
  845 
  846 EditorPanel::~EditorPanel ()
  847 {
  848     idle_register.destroy();
  849 
  850     history->setHistoryBeforeLineListener (nullptr);
  851     // the order is important!
  852     iareapanel->setBeforeAfterViews (nullptr, iareapanel);
  853     delete iareapanel;
  854     iareapanel = nullptr;
  855 
  856     if (beforeIpc) {
  857         beforeIpc->stopProcessing ();
  858     }
  859 
  860     delete beforeIarea;
  861     beforeIarea = nullptr;
  862 
  863     if (beforeIpc) {
  864         beforeIpc->setPreviewImageListener (nullptr);
  865     }
  866 
  867     delete beforePreviewHandler;
  868     beforePreviewHandler = nullptr;
  869 
  870     if (beforeIpc) {
  871         rtengine::StagedImageProcessor::destroy (beforeIpc);
  872     }
  873 
  874     beforeIpc = nullptr;
  875 
  876     close ();
  877 
  878     if (epih->pending) {
  879         epih->destroyed = true;
  880     } else {
  881         delete epih;
  882     }
  883 
  884     delete tpc;
  885 
  886     delete leftsubbox;
  887     delete leftbox;
  888     delete vsubboxright;
  889     delete vboxright;
  890 
  891     //delete saveAsDialog;
  892     if (catalogPane) {
  893         delete catalogPane;
  894     }
  895 
  896     if (iTopPanel_1_Show) {
  897         delete iTopPanel_1_Show;
  898     }
  899 
  900     if (iTopPanel_1_Hide) {
  901         delete iTopPanel_1_Hide;
  902     }
  903 
  904     if (iHistoryShow) {
  905         delete iHistoryShow;
  906     }
  907 
  908     if (iHistoryHide) {
  909         delete iHistoryHide;
  910     }
  911 
  912     if (iBeforeLockON) {
  913         delete iBeforeLockON;
  914     }
  915 
  916     if (iBeforeLockOFF) {
  917         delete iBeforeLockOFF;
  918     }
  919 
  920     if (iRightPanel_1_Show) {
  921         delete iRightPanel_1_Show;
  922     }
  923 
  924     if (iRightPanel_1_Hide) {
  925         delete iRightPanel_1_Hide;
  926     }
  927 }
  928 
  929 void EditorPanel::leftPaneButtonReleased (GdkEventButton *event)
  930 {
  931     if (event->button == 1) {
  932         // Button 1 released : it's a resize
  933         options.historyPanelWidth = hpanedl->get_position();
  934     }
  935 
  936     /*else if (event->button == 3) {
  937     }*/
  938 }
  939 
  940 void EditorPanel::rightPaneButtonReleased (GdkEventButton *event)
  941 {
  942     if (event->button == 1) {
  943         int winW, winH;
  944         parentWindow->get_size (winW, winH);
  945         // Button 1 released : it's a resize
  946         options.toolPanelWidth = winW - hpanedr->get_position();
  947     }
  948 
  949     /*else if (event->button == 3) {
  950     }*/
  951 }
  952 
  953 void EditorPanel::writeOptions()
  954 {
  955     if (profilep) {
  956         profilep->writeOptions();
  957     }
  958 
  959     if (tpc) {
  960         tpc->writeOptions();
  961     }
  962 }
  963 
  964 
  965 void EditorPanel::writeToolExpandedStatus (std::vector<int> &tpOpen)
  966 {
  967     if (tpc) {
  968         tpc->writeToolExpandedStatus (tpOpen);
  969     }
  970 }
  971 
  972 void EditorPanel::showTopPanel (bool show)
  973 {
  974     if (tbTopPanel_1->get_active() != show) {
  975         tbTopPanel_1->set_active (show);
  976     }
  977 }
  978 
  979 void EditorPanel::setAspect ()
  980 {
  981     int winW, winH;
  982     parentWindow->get_size (winW, winH);
  983     hpanedl->set_position (options.historyPanelWidth);
  984     hpanedr->set_position (winW - options.toolPanelWidth);
  985 
  986     // initialize components
  987     if (info->get_active() != options.showInfo) {
  988         info->set_active (options.showInfo);
  989     }
  990 }
  991 
  992 void EditorPanel::on_realize ()
  993 {
  994     realized = true;
  995     Gtk::VBox::on_realize ();
  996     // This line is needed to avoid autoexpansion of the window :-/
  997     //vboxright->set_size_request (options.toolPanelWidth, -1);
  998     tpc->updateToolState();
  999 }
 1000 
 1001 void EditorPanel::open (Thumbnail* tmb, rtengine::InitialImage* isrc)
 1002 {
 1003 
 1004     close();
 1005 
 1006     isProcessing = true; // prevents closing-on-init
 1007 
 1008     // initialize everything
 1009     openThm = tmb;
 1010     openThm->increaseRef ();
 1011 
 1012     fname = openThm->getFileName();
 1013     lastSaveAsFileName = removeExtension (Glib::path_get_basename (fname));
 1014 
 1015     previewHandler = new PreviewHandler ();
 1016 
 1017     this->isrc = isrc;
 1018     ipc = rtengine::StagedImageProcessor::create (isrc);
 1019     ipc->setProgressListener (this);
 1020     colorMgmtToolBar->updateProcessor();
 1021     ipc->setPreviewImageListener (previewHandler);
 1022     ipc->setPreviewScale (10);  // Important
 1023     tpc->initImage (ipc, tmb->getType() == FT_Raw);
 1024     ipc->setHistogramListener (this);
 1025     iareapanel->imageArea->indClippedPanel->silentlyDisableSharpMask();
 1026 
 1027 //    iarea->fitZoom ();   // tell to the editorPanel that the next image has to be fitted to the screen
 1028     iareapanel->imageArea->setPreviewHandler (previewHandler);
 1029     iareapanel->imageArea->setImProcCoordinator (ipc);
 1030     navigator->previewWindow->setPreviewHandler (previewHandler);
 1031     navigator->previewWindow->setImageArea (iareapanel->imageArea);
 1032 
 1033     rtengine::ImageSource* is = isrc->getImageSource();
 1034     is->setProgressListener ( this );
 1035 
 1036     // try to load the last saved parameters from the cache or from the paramfile file
 1037     ProcParams* ldprof = openThm->createProcParamsForUpdate (true, false); // will be freed by initProfile
 1038 
 1039     // initialize profile
 1040     Glib::ustring defProf = openThm->getType() == FT_Raw ? options.defProfRaw : options.defProfImg;
 1041     profilep->initProfile (defProf, ldprof);
 1042     profilep->setInitialFileName (fname);
 1043 
 1044     openThm->addThumbnailListener (this);
 1045     info_toggled ();
 1046 
 1047     if (beforeIarea) {
 1048         beforeAfterToggled();
 1049         beforeAfterToggled();
 1050     }
 1051 
 1052     // If in single tab mode, the main crop window is not constructed the very first time
 1053     // since there was no resize event
 1054     if (iareapanel->imageArea->mainCropWindow) {
 1055         iareapanel->imageArea->mainCropWindow->cropHandler.newImage (ipc, false);
 1056     } else {
 1057         Gtk::Allocation alloc;
 1058         iareapanel->imageArea->on_resized (alloc);
 1059 
 1060         // When passing a photo as an argument to the RawTherapee executable, the user wants
 1061         // this auto-loaded photo's thumbnail to be selected and visible in the Filmstrip.
 1062         EditorPanel::syncFileBrowser();
 1063     }
 1064 
 1065     history->resetSnapShotNumber();
 1066     navigator->setInvalid(ipc->getFullWidth(),ipc->getFullHeight());
 1067 }
 1068 
 1069 void EditorPanel::close ()
 1070 {
 1071     if (ipc) {
 1072         saveProfile ();
 1073         // close image processor and the current thumbnail
 1074         tpc->closeImage ();    // this call stops image processing
 1075         tpc->writeOptions ();
 1076         rtengine::ImageSource* is = isrc->getImageSource();
 1077         is->setProgressListener ( nullptr );
 1078 
 1079         if (ipc) {
 1080             ipc->setPreviewImageListener (nullptr);
 1081         }
 1082 
 1083         if (beforeIpc) {
 1084             beforeIpc->setPreviewImageListener (nullptr);
 1085         }
 1086 
 1087         delete previewHandler;
 1088         previewHandler = nullptr;
 1089 
 1090         if (iareapanel) {
 1091             iareapanel->imageArea->setPreviewHandler (nullptr);
 1092             iareapanel->imageArea->setImProcCoordinator (nullptr);
 1093             tpc->editModeSwitchedOff();
 1094         }
 1095 
 1096         rtengine::StagedImageProcessor::destroy (ipc);
 1097         ipc = nullptr;
 1098         navigator->previewWindow->setPreviewHandler (nullptr);
 1099 
 1100         // If the file was deleted somewhere, the openThm.descreaseRef delete the object, but we don't know here
 1101         if (Glib::file_test (fname, Glib::FILE_TEST_EXISTS)) {
 1102             openThm->removeThumbnailListener (this);
 1103             openThm->decreaseRef ();
 1104         }
 1105     }
 1106 }
 1107 
 1108 void EditorPanel::saveProfile ()
 1109 {
 1110     if (!ipc || !openThm) {
 1111         return;
 1112     }
 1113 
 1114     // If the file was deleted, do not generate ghost entries
 1115     if (Glib::file_test (fname, Glib::FILE_TEST_EXISTS)) {
 1116         ProcParams params;
 1117         ipc->getParams (&params);
 1118 
 1119         // Will call updateCache, which will update both the cached and sidecar files if necessary
 1120         openThm->setProcParams (params, nullptr, EDITOR);
 1121     }
 1122 }
 1123 
 1124 Glib::ustring EditorPanel::getShortName ()
 1125 {
 1126     if (openThm) {
 1127         return Glib::path_get_basename (openThm->getFileName ());
 1128     } else {
 1129         return "";
 1130     }
 1131 }
 1132 
 1133 Glib::ustring EditorPanel::getFileName ()
 1134 {
 1135     if (openThm) {
 1136         return openThm->getFileName ();
 1137     } else {
 1138         return "";
 1139     }
 1140 }
 1141 
 1142 // TODO!!!
 1143 void EditorPanel::procParamsChanged(
 1144     const rtengine::procparams::ProcParams* params,
 1145     const rtengine::ProcEvent& ev,
 1146     const Glib::ustring& descr,
 1147     const ParamsEdited* paramsEdited
 1148 )
 1149 {
 1150 
 1151 //    if (ev!=EvPhotoLoaded)
 1152 //        saveLabel->set_markup (Glib::ustring("<span foreground=\"#AA0000\" weight=\"bold\">") + M("MAIN_BUTTON_SAVE") + "</span>");
 1153 
 1154     rtengine::eSensorType sensorType = isrc->getImageSource()->getSensorType();
 1155 
 1156     selectedFrame = 0;
 1157     if (sensorType == rtengine::ST_BAYER) {
 1158         selectedFrame = params->raw.bayersensor.imageNum;
 1159     //} else if (sensorType == rtengine::ST_FUJI_XTRANS) {
 1160     //    selectedFrame = params->raw.xtranssensor.imageNum;
 1161     }
 1162     selectedFrame = rtengine::LIM<int>(selectedFrame, 0, isrc->getImageSource()->getMetaData()->getFrameCount() - 1);
 1163 
 1164     info_toggled();
 1165 }
 1166 
 1167 void EditorPanel::clearParamChanges()
 1168 {
 1169 }
 1170 
 1171 void EditorPanel::setProgress(double p)
 1172 {
 1173     MyProgressBar* const pl = progressLabel;
 1174 
 1175     idle_register.add(
 1176         [p, pl]() -> bool
 1177         {
 1178             setprogressStrUI(p, {}, pl);
 1179             return false;
 1180         }
 1181     );
 1182 }
 1183 
 1184 void EditorPanel::setProgressStr(const Glib::ustring& str)
 1185 {
 1186     MyProgressBar* const pl = progressLabel;
 1187 
 1188     idle_register.add(
 1189         [str, pl]() -> bool
 1190         {
 1191             setprogressStrUI(-1.0, str, pl);
 1192             return false;
 1193         }
 1194     );
 1195 }
 1196 
 1197 void EditorPanel::setProgressState(bool inProcessing)
 1198 {
 1199     epih->pending++;
 1200 
 1201     idle_register.add(
 1202         [this, inProcessing]() -> bool
 1203         {
 1204             if (epih->destroyed)
 1205             {
 1206                 if (epih->pending == 1) {
 1207                     delete epih;
 1208                 } else {
 1209                     --epih->pending;
 1210                 }
 1211 
 1212                 return false;
 1213             }
 1214 
 1215             epih->epanel->refreshProcessingState(inProcessing);
 1216             --epih->pending;
 1217 
 1218             return false;
 1219         }
 1220     );
 1221 }
 1222 
 1223 void EditorPanel::error(const Glib::ustring& descr)
 1224 {
 1225 }
 1226 
 1227 void EditorPanel::error(const Glib::ustring& title, const Glib::ustring& descr)
 1228 {
 1229     epih->pending++;
 1230 
 1231     idle_register.add(
 1232         [this, descr, title]() -> bool
 1233         {
 1234             if (epih->destroyed) {
 1235                 if (epih->pending == 1) {
 1236                     delete epih;
 1237                 } else {
 1238                     --epih->pending;
 1239                 }
 1240 
 1241                 return false;
 1242             }
 1243 
 1244             epih->epanel->displayError(title, descr);
 1245             --epih->pending;
 1246 
 1247             return false;
 1248         }
 1249     );
 1250 }
 1251 
 1252 void EditorPanel::displayError(const Glib::ustring& title, const Glib::ustring& descr)
 1253 {
 1254     GtkWidget* msgd = gtk_message_dialog_new_with_markup (nullptr,
 1255                       GTK_DIALOG_DESTROY_WITH_PARENT,
 1256                       GTK_MESSAGE_ERROR,
 1257                       GTK_BUTTONS_OK,
 1258                       "<b>%s</b>",
 1259                       descr.data());
 1260     gtk_window_set_title ((GtkWindow*)msgd, title.data());
 1261     g_signal_connect_swapped (msgd, "response",
 1262                               G_CALLBACK (gtk_widget_destroy),
 1263                               msgd);
 1264     gtk_widget_show_all (msgd);
 1265 }
 1266 
 1267 // This is only called from the ThreadUI, so within the gtk thread
 1268 void EditorPanel::refreshProcessingState (bool inProcessingP)
 1269 {
 1270     double val;
 1271     Glib::ustring str;
 1272 
 1273     if (inProcessingP) {
 1274         if (processingStartedTime == 0) {
 1275             processingStartedTime = ::time (nullptr);
 1276         }
 1277 
 1278         val = 1.0;
 1279         str = "PROGRESSBAR_PROCESSING";
 1280     } else {
 1281         // Set proc params of thumbnail. It saves it into the cache and updates the file browser.
 1282         if (ipc && openThm && tpc->getChangedState()) {
 1283             rtengine::procparams::ProcParams pparams;
 1284             ipc->getParams (&pparams);
 1285             openThm->setProcParams (pparams, nullptr, EDITOR, false);
 1286         }
 1287 
 1288         // Ring a sound if it was a long event
 1289         if (processingStartedTime != 0) {
 1290             time_t curTime = ::time (nullptr);
 1291 
 1292             if (::difftime (curTime, processingStartedTime) > options.sndLngEditProcDoneSecs) {
 1293                 SoundManager::playSoundAsync (options.sndLngEditProcDone);
 1294             }
 1295 
 1296             processingStartedTime = 0;
 1297         }
 1298 
 1299         // Set progress bar "done"
 1300         val = 0.0;
 1301         str = "PROGRESSBAR_READY";
 1302 
 1303 #ifdef WIN32
 1304 
 1305         // Maybe accessing "parent", which is a Gtk object, can justify to get the Gtk lock...
 1306         if (!firstProcessingDone && static_cast<RTWindow*> (parent)->getIsFullscreen()) {
 1307             parent->fullscreen();
 1308         }
 1309 
 1310 #endif
 1311         firstProcessingDone = true;
 1312     }
 1313 
 1314     isProcessing = inProcessingP;
 1315 
 1316     setprogressStrUI(val, str, progressLabel);
 1317 }
 1318 
 1319 void EditorPanel::info_toggled ()
 1320 {
 1321 
 1322     Glib::ustring infoString;
 1323     Glib::ustring expcomp;
 1324 
 1325     if (!ipc || !openThm) {
 1326         return;
 1327     }
 1328 
 1329     const rtengine::FramesMetaData* idata = ipc->getInitialImage()->getMetaData();
 1330 
 1331     if (idata && idata->hasExif(selectedFrame)) {
 1332         infoString = Glib::ustring::compose ("%1 + %2\n<span size=\"small\">f/</span><span size=\"large\">%3</span>  <span size=\"large\">%4</span><span size=\"small\">s</span>  <span size=\"small\">%5</span><span size=\"large\">%6</span>  <span size=\"large\">%7</span><span size=\"small\">mm</span>",
 1333                                               Glib::ustring (idata->getMake() + " " + idata->getModel()),
 1334                                               Glib::ustring (idata->getLens()),
 1335                                               Glib::ustring (idata->apertureToString (idata->getFNumber(selectedFrame))),
 1336                                               Glib::ustring (idata->shutterToString (idata->getShutterSpeed(selectedFrame))),
 1337                                               M ("QINFO_ISO"), idata->getISOSpeed(selectedFrame),
 1338                                               Glib::ustring::format (std::setw (3), std::fixed, std::setprecision (2), idata->getFocalLen(selectedFrame)));
 1339 
 1340         expcomp = Glib::ustring (idata->expcompToString (idata->getExpComp(selectedFrame), true)); // maskZeroexpcomp
 1341 
 1342         if (!expcomp.empty ()) {
 1343             infoString = Glib::ustring::compose ("%1  <span size=\"large\">%2</span><span size=\"small\">EV</span>",
 1344                                                   infoString,
 1345                                                   expcomp /*Glib::ustring(idata->expcompToString(idata->getExpComp()))*/);
 1346         }
 1347 
 1348         infoString = Glib::ustring::compose ("%1\n<span size=\"small\">%2</span><span>%3</span>",
 1349                                               infoString,
 1350                                               escapeHtmlChars (Glib::path_get_dirname (openThm->getFileName())) + G_DIR_SEPARATOR_S,
 1351                                               escapeHtmlChars (Glib::path_get_basename (openThm->getFileName()))  );
 1352 
 1353         int ww = ipc->getFullWidth();
 1354         int hh = ipc->getFullHeight();
 1355         //megapixels
 1356         infoString = Glib::ustring::compose ("%1\n<span size=\"small\">%2 MP (%3x%4)</span>",
 1357                                              infoString,
 1358                                              Glib::ustring::format (std::setw (4), std::fixed, std::setprecision (1), (float)ww * hh / 1000000),
 1359                                              ww, hh);
 1360 
 1361         //adding special characteristics
 1362         bool isHDR = idata->getHDR();
 1363         bool isPixelShift = idata->getPixelShift();
 1364         unsigned int numFrames = idata->getFrameCount();
 1365         if (isHDR) {
 1366             infoString = Glib::ustring::compose ("%1\n" + M("QINFO_HDR"), infoString, numFrames);
 1367             if (numFrames == 1) {
 1368                 int sampleFormat = idata->getSampleFormat(selectedFrame);
 1369                 infoString = Glib::ustring::compose ("%1 / %2", infoString, M(Glib::ustring::compose("SAMPLEFORMAT_%1", sampleFormat)));
 1370             }
 1371         } else if (isPixelShift) {
 1372             infoString = Glib::ustring::compose ("%1\n" + M("QINFO_PIXELSHIFT"), infoString, numFrames);
 1373         } else if (numFrames > 1) {
 1374             infoString = Glib::ustring::compose ("%1\n" + M("QINFO_FRAMECOUNT"), infoString, numFrames);
 1375         }
 1376     } else {
 1377         infoString = M ("QINFO_NOEXIF");
 1378     }
 1379 
 1380     iareapanel->imageArea->setInfoText (std::move(infoString));
 1381     iareapanel->imageArea->infoEnabled (info->get_active ());
 1382 }
 1383 
 1384 void EditorPanel::hideHistoryActivated ()
 1385 {
 1386 
 1387     removeIfThere (hpanedl, leftbox, false);
 1388 
 1389     if (hidehp->get_active()) {
 1390         hpanedl->pack1 (*leftbox, false, false);
 1391     }
 1392 
 1393     options.showHistory = hidehp->get_active();
 1394 
 1395     if (options.showHistory) {
 1396         hidehp->set_image (*iHistoryHide);
 1397     } else {
 1398         hidehp->set_image (*iHistoryShow);
 1399     }
 1400 
 1401     tbShowHideSidePanels_managestate();
 1402 }
 1403 
 1404 
 1405 void EditorPanel::tbRightPanel_1_toggled ()
 1406 {
 1407     /*
 1408         removeIfThere (hpanedr, vboxright, false);
 1409         if (tbRightPanel_1->get_active()){
 1410             hpanedr->pack2(*vboxright, false, true);
 1411             tbRightPanel_1->set_image (*iRightPanel_1_Hide);
 1412         }
 1413         else {
 1414             tbRightPanel_1->set_image (*iRightPanel_1_Show);
 1415         }
 1416         tbShowHideSidePanels_managestate();
 1417         */
 1418     if (vboxright) {
 1419         if (tbRightPanel_1->get_active()) {
 1420             vboxright->show();
 1421             tbRightPanel_1->set_image (*iRightPanel_1_Hide);
 1422         } else {
 1423             vboxright->hide();
 1424             tbRightPanel_1->set_image (*iRightPanel_1_Show);
 1425         }
 1426 
 1427         tbShowHideSidePanels_managestate();
 1428     }
 1429 }
 1430 
 1431 void EditorPanel::tbTopPanel_1_visible (bool visible)
 1432 {
 1433     if (!tbTopPanel_1) {
 1434         return;
 1435     }
 1436 
 1437     if (visible) {
 1438         tbTopPanel_1->show();
 1439     } else {
 1440         tbTopPanel_1->hide();
 1441     }
 1442 }
 1443 
 1444 void EditorPanel::tbTopPanel_1_toggled ()
 1445 {
 1446 
 1447     if (catalogPane) { // catalogPane does not exist in multitab mode
 1448 
 1449         if (tbTopPanel_1->get_active()) {
 1450             catalogPane->show();
 1451             tbTopPanel_1->set_image (*iTopPanel_1_Hide);
 1452             options.editorFilmStripOpened = true;
 1453         } else {
 1454             catalogPane->hide();
 1455             tbTopPanel_1->set_image (*iTopPanel_1_Show);
 1456             options.editorFilmStripOpened = false;
 1457         }
 1458 
 1459         tbShowHideSidePanels_managestate();
 1460     }
 1461 }
 1462 
 1463 /*
 1464  * WARNING: Take care of the simpleEditor value when adding or modifying shortcut keys,
 1465  *          since handleShortcutKey is now also triggered in simple editor mode
 1466  */
 1467 bool EditorPanel::handleShortcutKey (GdkEventKey* event)
 1468 {
 1469 
 1470     bool ctrl = event->state & GDK_CONTROL_MASK;
 1471     bool shift = event->state & GDK_SHIFT_MASK;
 1472     bool alt = event->state & GDK_MOD1_MASK;
 1473 #ifdef __WIN32__
 1474     bool altgr = event->state & GDK_MOD2_MASK;
 1475 #else
 1476     bool altgr = event->state & GDK_MOD5_MASK;
 1477 #endif
 1478 
 1479     // Editor Layout
 1480     switch (event->keyval) {
 1481         case GDK_KEY_L:
 1482             if (tbTopPanel_1) {
 1483                 tbTopPanel_1->set_active (!tbTopPanel_1->get_active());    // toggle top panel
 1484             }
 1485 
 1486             if (ctrl) {
 1487                 hidehp->set_active (!hidehp->get_active());    // toggle History (left panel)
 1488             }
 1489 
 1490             if (alt) {
 1491                 tbRightPanel_1->set_active (!tbRightPanel_1->get_active());    // toggle right panel
 1492             }
 1493 
 1494             return true;
 1495             break;
 1496 
 1497         case GDK_KEY_l:
 1498             if (!shift && !alt /*&& !ctrl*/) {
 1499                 hidehp->set_active (!hidehp->get_active()); // toggle History (left panel)
 1500                 return true;
 1501             }
 1502 
 1503             if (alt && !ctrl) { // toggle right panel
 1504                 tbRightPanel_1->set_active (!tbRightPanel_1->get_active());
 1505                 return true;
 1506             }
 1507 
 1508             if (alt && ctrl) { // toggle left and right panels
 1509                 hidehp->set_active (!hidehp->get_active());
 1510                 tbRightPanel_1->set_active (!tbRightPanel_1->get_active());
 1511                 return true;
 1512             }
 1513 
 1514             break;
 1515 
 1516         case GDK_KEY_m: // Maximize preview panel: hide top AND right AND history panels
 1517             if (!ctrl && !alt) {
 1518                 toggleSidePanels();
 1519                 return true;
 1520             }
 1521 
 1522             break;
 1523 
 1524         case GDK_KEY_M: // Maximize preview panel: hide top AND right AND history panels AND (fit image preview)
 1525             if (!ctrl && !alt) {
 1526                 toggleSidePanelsZoomFit();
 1527                 return true;
 1528             }
 1529 
 1530             break;
 1531     }
 1532 
 1533 #ifdef __WIN32__
 1534 
 1535     if (!alt && !ctrl && !altgr && event->hardware_keycode == 0x39 ) {
 1536         iareapanel->imageArea->previewModePanel->togglebackColor();
 1537         return true;
 1538     }
 1539 
 1540 #else
 1541 
 1542     if (!alt && !ctrl && !altgr && event->hardware_keycode == 0x12 ) {
 1543         iareapanel->imageArea->previewModePanel->togglebackColor();
 1544         return true;
 1545     }
 1546 
 1547 #endif
 1548 
 1549     if (!alt) {
 1550         if (!ctrl) {
 1551             // Normal
 1552             switch (event->keyval) {
 1553                 case GDK_KEY_bracketright:
 1554                     tpc->coarse->rotateRight();
 1555                     return true;
 1556 
 1557                 case GDK_KEY_bracketleft:
 1558                     tpc->coarse->rotateLeft();
 1559                     return true;
 1560 
 1561                 case GDK_KEY_i:
 1562                 case GDK_KEY_I:
 1563                     info->set_active (!info->get_active());
 1564                     return true;
 1565 
 1566                 case GDK_KEY_B:
 1567                     beforeAfter->set_active (!beforeAfter->get_active());
 1568                     return true;
 1569 
 1570                 case GDK_KEY_plus:
 1571                 case GDK_KEY_equal:
 1572                 case GDK_KEY_KP_Add:
 1573                     iareapanel->imageArea->zoomPanel->zoomInClicked();
 1574                     return true;
 1575 
 1576                 case GDK_KEY_minus:
 1577                 case GDK_KEY_underscore:
 1578                 case GDK_KEY_KP_Subtract:
 1579                     iareapanel->imageArea->zoomPanel->zoomOutClicked();
 1580                     return true;
 1581 
 1582                 case GDK_KEY_z://GDK_1
 1583                     iareapanel->imageArea->zoomPanel->zoom11Clicked();
 1584                     return true;
 1585 
 1586                 /*
 1587                 #ifndef __WIN32__
 1588                                 case GDK_KEY_9: // toggle background color of the preview
 1589                                     iareapanel->imageArea->previewModePanel->togglebackColor();
 1590                                     return true;
 1591                 #endif
 1592                 */
 1593                 case GDK_KEY_r: //preview mode Red
 1594                     iareapanel->imageArea->previewModePanel->toggleR();
 1595                     return true;
 1596 
 1597                 case GDK_KEY_g: //preview mode Green
 1598                     iareapanel->imageArea->previewModePanel->toggleG();
 1599                     return true;
 1600 
 1601                 case GDK_KEY_b: //preview mode Blue
 1602                     iareapanel->imageArea->previewModePanel->toggleB();
 1603                     return true;
 1604 
 1605                 case GDK_KEY_p: //preview mode Sharpening Contrast mask
 1606                     iareapanel->imageArea->indClippedPanel->toggleSharpMask();
 1607                     return true;
 1608 
 1609                 case GDK_KEY_v: //preview mode Luminosity
 1610                     iareapanel->imageArea->previewModePanel->toggleL();
 1611                     return true;
 1612 
 1613                 case GDK_KEY_F: //preview mode Focus Mask
 1614                     iareapanel->imageArea->indClippedPanel->toggleFocusMask();
 1615                     return true;
 1616 
 1617                 case GDK_KEY_less:
 1618                     iareapanel->imageArea->indClippedPanel->toggleClipped (false);
 1619                     return true;
 1620 
 1621                 case GDK_KEY_greater:
 1622                     iareapanel->imageArea->indClippedPanel->toggleClipped (true);
 1623                     return true;
 1624 
 1625                 case GDK_KEY_f:
 1626                     iareapanel->imageArea->zoomPanel->zoomFitCropClicked();
 1627                     return true;
 1628 
 1629                 case GDK_KEY_F5:
 1630                     openThm->openDefaultViewer ((event->state & GDK_SHIFT_MASK) ? 2 : 1);
 1631                     return true;
 1632 
 1633                 case GDK_KEY_y: // synchronize filebrowser with image in Editor
 1634                     if (!simpleEditor && fPanel && !fname.empty()) {
 1635                         fPanel->fileCatalog->selectImage (fname, false);
 1636                         return true;
 1637                     }
 1638 
 1639                     break; // to avoid gcc complain
 1640 
 1641                 case GDK_KEY_x: // clear filters and synchronize filebrowser with image in Editor
 1642                     if (!simpleEditor && fPanel && !fname.empty()) {
 1643                         fPanel->fileCatalog->selectImage (fname, true);
 1644                         return true;
 1645                     }
 1646 
 1647                     break; // to avoid gcc complain
 1648             }
 1649         } else {
 1650             // With control
 1651             switch (event->keyval) {
 1652                 case GDK_KEY_S:
 1653                     saveProfile();
 1654                     setProgressStr (M ("PROGRESSBAR_PROCESSING_PROFILESAVED"));
 1655                     return true;
 1656 
 1657                 case GDK_KEY_s:
 1658                     if (!gimpPlugin) {
 1659                         saveAsPressed();
 1660                     }
 1661 
 1662                     return true;
 1663 
 1664                 case GDK_KEY_b:
 1665                     if (!gimpPlugin && !simpleEditor) {
 1666                         queueImgPressed();
 1667                     }
 1668 
 1669                     return true;
 1670 
 1671                 case GDK_KEY_e:
 1672                     if (!gimpPlugin) {
 1673                         sendToGimpPressed();
 1674                     }
 1675 
 1676                     return true;
 1677 
 1678                 case GDK_KEY_z:
 1679                     history->undo ();
 1680                     return true;
 1681 
 1682                 case GDK_KEY_Z:
 1683                     history->redo ();
 1684                     return true;
 1685 
 1686                 case GDK_KEY_F5:
 1687                     openThm->openDefaultViewer (3);
 1688                     return true;
 1689             }
 1690         } //if (!ctrl)
 1691     } //if (!alt)
 1692 
 1693     if (alt) {
 1694         switch (event->keyval) {
 1695             case GDK_KEY_s:
 1696                 history->addBookmarkPressed ();
 1697                 setProgressStr (M ("PROGRESSBAR_SNAPSHOT_ADDED"));
 1698                 return true;
 1699 
 1700             case GDK_KEY_f:
 1701                 iareapanel->imageArea->zoomPanel->zoomFitClicked();
 1702                 return true;
 1703         }
 1704     }
 1705 
 1706     if (shift) {
 1707         switch (event->keyval) {
 1708             case GDK_KEY_F3: // open Previous image from Editor's perspective
 1709                 if (!simpleEditor && fPanel && !fname.empty()) {
 1710                     EditorPanel::openPreviousEditorImage();
 1711                     return true;
 1712                 }
 1713 
 1714                 break; // to avoid gcc complain
 1715 
 1716             case GDK_KEY_F4: // open next image from Editor's perspective
 1717                 if (!simpleEditor && fPanel && !fname.empty()) {
 1718                     EditorPanel::openNextEditorImage();
 1719                     return true;
 1720                 }
 1721 
 1722                 break; // to avoid gcc complain
 1723         }
 1724     }
 1725 
 1726     if (tpc->getToolBar() && tpc->getToolBar()->handleShortcutKey (event)) {
 1727         return true;
 1728     }
 1729 
 1730     if (tpc->handleShortcutKey (event)) {
 1731         return true;
 1732     }
 1733 
 1734     if (!simpleEditor && fPanel) {
 1735         if (fPanel->handleShortcutKey (event)) {
 1736             return true;
 1737         }
 1738     }
 1739 
 1740     return false;
 1741 }
 1742 
 1743 void EditorPanel::procParamsChanged (Thumbnail* thm, int whoChangedIt)
 1744 {
 1745 
 1746     if (whoChangedIt != EDITOR) {
 1747         PartialProfile pp (true);
 1748         pp.set (true);
 1749         * (pp.pparams) = openThm->getProcParams();
 1750         tpc->profileChange (&pp, rtengine::EvProfileChangeNotification, M ("PROGRESSDLG_PROFILECHANGEDINBROWSER"));
 1751         pp.deleteInstance();
 1752     }
 1753 }
 1754 
 1755 bool EditorPanel::idle_saveImage (ProgressConnector<rtengine::IImagefloat*> *pc, Glib::ustring fname, SaveFormat sf, rtengine::procparams::ProcParams &pparams)
 1756 {
 1757     rtengine::IImagefloat* img = pc->returnValue();
 1758     delete pc;
 1759 
 1760     if ( img ) {
 1761         setProgressStr (M ("GENERAL_SAVE"));
 1762         setProgress (0.9f);
 1763 
 1764         ProgressConnector<int> *ld = new ProgressConnector<int>();
 1765         img->setSaveProgressListener (parent->getProgressListener());
 1766 
 1767         if (sf.format == "tif")
 1768             ld->startFunc (sigc::bind (sigc::mem_fun (img, &rtengine::IImagefloat::saveAsTIFF), fname, sf.tiffBits, sf.tiffFloat, sf.tiffUncompressed),
 1769                            sigc::bind (sigc::mem_fun (*this, &EditorPanel::idle_imageSaved), ld, img, fname, sf, pparams));
 1770         else if (sf.format == "png")
 1771             ld->startFunc (sigc::bind (sigc::mem_fun (img, &rtengine::IImagefloat::saveAsPNG), fname, sf.pngBits),
 1772                            sigc::bind (sigc::mem_fun (*this, &EditorPanel::idle_imageSaved), ld, img, fname, sf, pparams));
 1773         else if (sf.format == "jpg")
 1774             ld->startFunc (sigc::bind (sigc::mem_fun (img, &rtengine::IImagefloat::saveAsJPEG), fname, sf.jpegQuality, sf.jpegSubSamp),
 1775                            sigc::bind (sigc::mem_fun (*this, &EditorPanel::idle_imageSaved), ld, img, fname, sf, pparams));
 1776         else {
 1777             delete ld;
 1778         }
 1779     } else {
 1780         Glib::ustring msg_ = Glib::ustring ("<b>") + fname + ": Error during image processing\n</b>";
 1781         Gtk::MessageDialog msgd (*parent, msg_, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
 1782         msgd.run ();
 1783 
 1784         saveimgas->set_sensitive (true);
 1785         sendtogimp->set_sensitive (true);
 1786         isProcessing = false;
 1787 
 1788     }
 1789 
 1790     rtengine::ImageSource* imgsrc = isrc->getImageSource ();
 1791     imgsrc->setProgressListener (this);
 1792     return false;
 1793 }
 1794 
 1795 bool EditorPanel::idle_imageSaved (ProgressConnector<int> *pc, rtengine::IImagefloat* img, Glib::ustring fname, SaveFormat sf, rtengine::procparams::ProcParams &pparams)
 1796 {
 1797     img->free ();
 1798 
 1799     if (! pc->returnValue() ) {
 1800         openThm->imageDeveloped ();
 1801 
 1802         // save processing parameters, if needed
 1803         if (sf.saveParams) {
 1804             // We keep the extension to avoid overwriting the profile when we have
 1805             // the same output filename with different extension
 1806             pparams.save (fname + ".out" + paramFileExtension);
 1807         }
 1808     } else {
 1809         error (M ("MAIN_MSG_CANNOTSAVE"), fname);
 1810     }
 1811 
 1812     saveimgas->set_sensitive (true);
 1813     sendtogimp->set_sensitive (true);
 1814 
 1815     parent->setProgressStr ("");
 1816     parent->setProgress (0.);
 1817 
 1818     setProgressState (false);
 1819 
 1820     delete pc;
 1821     SoundManager::playSoundAsync (options.sndBatchQueueDone);
 1822     isProcessing = false;
 1823     return false;
 1824 }
 1825 
 1826 BatchQueueEntry* EditorPanel::createBatchQueueEntry ()
 1827 {
 1828 
 1829     rtengine::procparams::ProcParams pparams;
 1830     ipc->getParams (&pparams);
 1831     //rtengine::ProcessingJob* job = rtengine::ProcessingJob::create (ipc->getInitialImage(), pparams);
 1832     rtengine::ProcessingJob* job = rtengine::ProcessingJob::create (openThm->getFileName (), openThm->getType() == FT_Raw, pparams);
 1833     int fullW = 0, fullH = 0;
 1834     isrc->getImageSource()->getFullSize (fullW, fullH, pparams.coarse.rotate == 90 || pparams.coarse.rotate == 270 ? TR_R90 : TR_NONE);
 1835     int prevh = BatchQueue::calcMaxThumbnailHeight();
 1836     int prevw = int ((size_t)fullW * (size_t)prevh / (size_t)fullH);
 1837     return new BatchQueueEntry (job, pparams, openThm->getFileName(), prevw, prevh, openThm, options.overwriteOutputFile);
 1838 }
 1839 
 1840 
 1841 
 1842 void EditorPanel::saveAsPressed ()
 1843 {
 1844     if (!ipc || !openThm) {
 1845         return;
 1846     }
 1847 
 1848     bool fnameOK = false;
 1849     Glib::ustring fnameOut;
 1850 
 1851     SaveAsDialog* saveAsDialog;
 1852     auto toplevel = static_cast<Gtk::Window*> (get_toplevel ());
 1853 
 1854     if (Glib::file_test (options.lastSaveAsPath, Glib::FILE_TEST_IS_DIR)) {
 1855         saveAsDialog = new SaveAsDialog (options.lastSaveAsPath, toplevel);
 1856     } else {
 1857         saveAsDialog = new SaveAsDialog (PlacesBrowser::userPicturesDir (), toplevel);
 1858     }
 1859 
 1860     saveAsDialog->set_default_size (options.saveAsDialogWidth, options.saveAsDialogHeight);
 1861     saveAsDialog->setInitialFileName (lastSaveAsFileName);
 1862     saveAsDialog->setImagePath (fname);
 1863 
 1864     do {
 1865         int result = saveAsDialog->run ();
 1866 
 1867         // The SaveAsDialog ensure that a filename has been specified
 1868         fnameOut = saveAsDialog->getFileName ();
 1869 
 1870         options.lastSaveAsPath = saveAsDialog->getDirectory ();
 1871         saveAsDialog->get_size (options.saveAsDialogWidth, options.saveAsDialogHeight);
 1872         options.autoSuffix = saveAsDialog->getAutoSuffix ();
 1873         options.saveMethodNum = saveAsDialog->getSaveMethodNum ();
 1874         lastSaveAsFileName = Glib::path_get_basename (removeExtension (fnameOut));
 1875         SaveFormat sf = saveAsDialog->getFormat ();
 1876         options.saveFormat = sf;
 1877         options.forceFormatOpts = saveAsDialog->getForceFormatOpts ();
 1878 
 1879         if (result != Gtk::RESPONSE_OK) {
 1880             break;
 1881         }
 1882 
 1883         if (saveAsDialog->getImmediately ()) {
 1884             // separate filename and the path to the destination directory
 1885             Glib::ustring dstdir = Glib::path_get_dirname (fnameOut);
 1886             Glib::ustring dstfname = Glib::path_get_basename (removeExtension (fnameOut));
 1887             Glib::ustring dstext = getExtension (fnameOut);
 1888 
 1889             if (saveAsDialog->getAutoSuffix()) {
 1890 
 1891                 Glib::ustring fnameTemp;
 1892 
 1893                 for (int tries = 0; tries < 100; tries++) {
 1894                     if (tries == 0) {
 1895                         fnameTemp = Glib::ustring::compose ("%1.%2", Glib::build_filename (dstdir,  dstfname), dstext);
 1896                     } else {
 1897                         fnameTemp = Glib::ustring::compose ("%1-%2.%3", Glib::build_filename (dstdir,  dstfname), tries, dstext);
 1898                     }
 1899 
 1900                     if (!Glib::file_test (fnameTemp, Glib::FILE_TEST_EXISTS)) {
 1901                         fnameOut = fnameTemp;
 1902                         fnameOK = true;
 1903                         break;
 1904                     }
 1905                 }
 1906             }
 1907 
 1908             // check if it exists
 1909             if (!fnameOK) {
 1910                 fnameOK = confirmOverwrite (*saveAsDialog, fnameOut);
 1911             }
 1912 
 1913             if (fnameOK) {
 1914                 isProcessing = true;
 1915                 // save image
 1916                 rtengine::procparams::ProcParams pparams;
 1917                 ipc->getParams (&pparams);
 1918                 rtengine::ProcessingJob* job = rtengine::ProcessingJob::create (ipc->getInitialImage(), pparams);
 1919 
 1920                 ProgressConnector<rtengine::IImagefloat*> *ld = new ProgressConnector<rtengine::IImagefloat*>();
 1921                 ld->startFunc (sigc::bind (sigc::ptr_fun (&rtengine::processImage), job, err, parent->getProgressListener(), false ),
 1922                                sigc::bind (sigc::mem_fun ( *this, &EditorPanel::idle_saveImage ), ld, fnameOut, sf, pparams));
 1923                 saveimgas->set_sensitive (false);
 1924                 sendtogimp->set_sensitive (false);
 1925             }
 1926         } else {
 1927             BatchQueueEntry* bqe = createBatchQueueEntry ();
 1928             bqe->outFileName = fnameOut;
 1929             bqe->saveFormat = saveAsDialog->getFormat ();
 1930             bqe->overwriteFile = !saveAsDialog->getAutoSuffix();
 1931             bqe->forceFormatOpts = saveAsDialog->getForceFormatOpts ();
 1932             parent->addBatchQueueJob (bqe, saveAsDialog->getToHeadOfQueue ());
 1933             fnameOK = true;
 1934         }
 1935 
 1936         // ask parent to redraw file browser
 1937         // ... or does it automatically when the tab is switched to it
 1938     } while (!fnameOK);
 1939 
 1940     saveAsDialog->hide();
 1941 
 1942     delete saveAsDialog;
 1943 }
 1944 
 1945 void EditorPanel::queueImgPressed ()
 1946 {
 1947     if (!ipc || !openThm) {
 1948         return;
 1949     }
 1950 
 1951     saveProfile ();
 1952     parent->addBatchQueueJob (createBatchQueueEntry ());
 1953 }
 1954 
 1955 void EditorPanel::sendToGimpPressed ()
 1956 {
 1957     if (!ipc || !openThm) {
 1958         return;
 1959     }
 1960 
 1961     // develop image
 1962     rtengine::procparams::ProcParams pparams;
 1963     ipc->getParams (&pparams);
 1964     rtengine::ProcessingJob* job = rtengine::ProcessingJob::create (ipc->getInitialImage(), pparams);
 1965     ProgressConnector<rtengine::IImagefloat*> *ld = new ProgressConnector<rtengine::IImagefloat*>();
 1966     ld->startFunc (sigc::bind (sigc::ptr_fun (&rtengine::processImage), job, err, parent->getProgressListener(), false ),
 1967                    sigc::bind (sigc::mem_fun ( *this, &EditorPanel::idle_sendToGimp ), ld, openThm->getFileName() ));
 1968     saveimgas->set_sensitive (false);
 1969     sendtogimp->set_sensitive (false);
 1970 }
 1971 
 1972 
 1973 bool EditorPanel::saveImmediately (const Glib::ustring &filename, const SaveFormat &sf)
 1974 {
 1975     rtengine::procparams::ProcParams pparams;
 1976     ipc->getParams (&pparams);
 1977 
 1978     rtengine::ProcessingJob *job = rtengine::ProcessingJob::create (ipc->getInitialImage(), pparams);
 1979 
 1980     // save immediately
 1981     rtengine::IImagefloat *img = rtengine::processImage (job, err, nullptr, false);
 1982 
 1983     int err = 0;
 1984 
 1985     if (gimpPlugin) {
 1986         err = img->saveAsTIFF (filename, 32, true, true);
 1987     } else if (sf.format == "tif") {
 1988         err = img->saveAsTIFF (filename, sf.tiffBits, sf.tiffFloat, sf.tiffUncompressed);
 1989     } else if (sf.format == "png") {
 1990         err = img->saveAsPNG (filename, sf.pngBits);
 1991     } else if (sf.format == "jpg") {
 1992         err = img->saveAsJPEG (filename, sf.jpegQuality, sf.jpegSubSamp);
 1993     } else {
 1994         err = 1;
 1995     }
 1996 
 1997     img->free();
 1998     return !err;
 1999 }
 2000 
 2001 
 2002 void EditorPanel::openPreviousEditorImage()
 2003 {
 2004     if (!simpleEditor && fPanel && !fname.empty()) {
 2005         fPanel->fileCatalog->openNextPreviousEditorImage (fname, false, NAV_PREVIOUS);
 2006     }
 2007 }
 2008 
 2009 void EditorPanel::openNextEditorImage()
 2010 {
 2011     if (!simpleEditor && fPanel && !fname.empty()) {
 2012         fPanel->fileCatalog->openNextPreviousEditorImage (fname, false, NAV_NEXT);
 2013     }
 2014 }
 2015 
 2016 void EditorPanel::syncFileBrowser()   // synchronize filebrowser with image in Editor
 2017 {
 2018     if (!simpleEditor && fPanel && !fname.empty()) {
 2019         fPanel->fileCatalog->selectImage (fname, false);
 2020     }
 2021 }
 2022 
 2023 void EditorPanel::histogramProfile_toggled()
 2024 {
 2025     options.rtSettings.HistogramWorking = toggleHistogramProfile->get_active();
 2026     colorMgmtToolBar->updateHistogram();
 2027 }
 2028 
 2029 bool EditorPanel::idle_sendToGimp ( ProgressConnector<rtengine::IImagefloat*> *pc, Glib::ustring fname)
 2030 {
 2031 
 2032     rtengine::IImagefloat* img = pc->returnValue();
 2033     delete pc;
 2034 
 2035     if (img) {
 2036         // get file name base
 2037         Glib::ustring shortname = removeExtension (Glib::path_get_basename (fname));
 2038         Glib::ustring dirname = Glib::get_tmp_dir ();
 2039         Glib::ustring fname = Glib::build_filename (dirname, shortname);
 2040 
 2041         SaveFormat sf;
 2042         sf.format = "tif";
 2043         sf.tiffBits = 16;
 2044         sf.tiffFloat = false;
 2045         sf.tiffUncompressed = true;
 2046         sf.saveParams = true;
 2047 
 2048         Glib::ustring fileName = Glib::ustring::compose ("%1.%2", fname, sf.format);
 2049 
 2050         // TODO: Just list all file with a suitable name instead of brute force...
 2051         int tries = 1;
 2052 
 2053         while (Glib::file_test (fileName, Glib::FILE_TEST_EXISTS) && tries < 1000) {
 2054             fileName = Glib::ustring::compose ("%1-%2.%3", fname, tries, sf.format);
 2055             tries++;
 2056         }
 2057 
 2058         if (tries == 1000) {
 2059             img->free ();
 2060             return false;
 2061         }
 2062 
 2063         ProgressConnector<int> *ld = new ProgressConnector<int>();
 2064         img->setSaveProgressListener (parent->getProgressListener());
 2065         ld->startFunc (sigc::bind (sigc::mem_fun (img, &rtengine::IImagefloat::saveAsTIFF), fileName, sf.tiffBits, sf.tiffFloat, sf.tiffUncompressed),
 2066                        sigc::bind (sigc::mem_fun (*this, &EditorPanel::idle_sentToGimp), ld, img, fileName));
 2067     } else {
 2068         Glib::ustring msg_ = Glib::ustring ("<b> Error during image processing\n</b>");
 2069         Gtk::MessageDialog msgd (*parent, msg_, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
 2070         msgd.run ();
 2071         saveimgas->set_sensitive (true);
 2072         sendtogimp->set_sensitive (true);
 2073     }
 2074 
 2075     return false;
 2076 }
 2077 
 2078 bool EditorPanel::idle_sentToGimp (ProgressConnector<int> *pc, rtengine::IImagefloat* img, Glib::ustring filename)
 2079 {
 2080     img->free ();
 2081     int errore = pc->returnValue();
 2082     delete pc;
 2083 
 2084     if (!errore) {
 2085         saveimgas->set_sensitive (true);
 2086         sendtogimp->set_sensitive (true);
 2087         parent->setProgressStr ("");
 2088         parent->setProgress (0.);
 2089         bool success = false;
 2090 
 2091         if (options.editorToSendTo == 1) {
 2092             success = ExtProgStore::openInGimp (filename);
 2093         } else if (options.editorToSendTo == 2) {
 2094             success = ExtProgStore::openInPhotoshop (filename);
 2095         } else if (options.editorToSendTo == 3) {
 2096             success = ExtProgStore::openInCustomEditor (filename);
 2097         }
 2098 
 2099         if (!success) {
 2100             Gtk::MessageDialog msgd (*parent, M ("MAIN_MSG_CANNOTSTARTEDITOR"), false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
 2101             msgd.set_secondary_text (M ("MAIN_MSG_CANNOTSTARTEDITOR_SECONDARY"));
 2102             msgd.set_title (M ("MAIN_BUTTON_SENDTOEDITOR"));
 2103             msgd.run ();
 2104         }
 2105     }
 2106 
 2107     return false;
 2108 }
 2109 
 2110 void EditorPanel::historyBeforeLineChanged (const rtengine::procparams::ProcParams& params)
 2111 {
 2112 
 2113     if (beforeIpc) {
 2114         ProcParams* pparams = beforeIpc->beginUpdateParams ();
 2115         *pparams = params;
 2116         beforeIpc->endUpdateParams (rtengine::EvProfileChanged);  // starts the IPC processing
 2117     }
 2118 }
 2119 
 2120 void EditorPanel::beforeAfterToggled ()
 2121 {
 2122 
 2123     if (!ipc) {
 2124         return;
 2125     }
 2126 
 2127     removeIfThere (beforeAfterBox,  beforeBox, false);
 2128     removeIfThere (afterBox,  afterHeaderBox, false);
 2129 
 2130     if (beforeIarea) {
 2131         if (beforeIpc) {
 2132             beforeIpc->stopProcessing ();
 2133         }
 2134 
 2135         iareapanel->setBeforeAfterViews (nullptr, iareapanel);
 2136         iareapanel->imageArea->iLinkedImageArea = nullptr;
 2137         delete beforeIarea;
 2138         beforeIarea = nullptr;
 2139 
 2140         if (beforeIpc) {
 2141             beforeIpc->setPreviewImageListener (nullptr);
 2142         }
 2143 
 2144         delete beforePreviewHandler;
 2145         beforePreviewHandler = nullptr;
 2146 
 2147         if (beforeIpc) {
 2148             rtengine::StagedImageProcessor::destroy (beforeIpc);
 2149         }
 2150 
 2151         beforeIpc = nullptr;
 2152     }
 2153 
 2154     if (beforeAfter->get_active ()) {
 2155 
 2156         int errorCode = 0;
 2157         rtengine::InitialImage *beforeImg = rtengine::InitialImage::load ( isrc->getImageSource ()->getFileName(),  openThm->getType() == FT_Raw, &errorCode, nullptr);
 2158 
 2159         if ( !beforeImg || errorCode ) {
 2160             return;
 2161         }
 2162 
 2163         beforeIarea = new ImageAreaPanel ();
 2164 
 2165         int HeaderBoxHeight = 17;
 2166 
 2167         beforeLabel = Gtk::manage (new Gtk::Label ());
 2168         beforeLabel->set_markup (Glib::ustring ("<b>") + M ("GENERAL_BEFORE") + "</b>");
 2169         tbBeforeLock = Gtk::manage (new Gtk::ToggleButton ());
 2170         tbBeforeLock->set_relief(Gtk::RELIEF_NONE);
 2171         tbBeforeLock->set_tooltip_markup (M ("MAIN_TOOLTIP_BEFOREAFTERLOCK"));
 2172         tbBeforeLock->signal_toggled().connect ( sigc::mem_fun (*this, &EditorPanel::tbBeforeLock_toggled) );
 2173         beforeHeaderBox = Gtk::manage (new Gtk::Box (Gtk::ORIENTATION_HORIZONTAL));
 2174         beforeHeaderBox->get_style_context()->add_class("smallbuttonbox");
 2175         beforeHeaderBox->pack_end (*tbBeforeLock, Gtk::PACK_SHRINK, 2);
 2176         beforeHeaderBox->pack_end (*beforeLabel, Gtk::PACK_SHRINK, 2);
 2177         beforeHeaderBox->set_size_request (0, HeaderBoxHeight);
 2178 
 2179         history->blistenerLock ? tbBeforeLock->set_image (*iBeforeLockON) : tbBeforeLock->set_image (*iBeforeLockOFF);
 2180         tbBeforeLock->set_active (history->blistenerLock);
 2181 
 2182         beforeBox = Gtk::manage (new Gtk::VBox ());
 2183         beforeBox->pack_start (*beforeHeaderBox, Gtk::PACK_SHRINK, 2);
 2184         beforeBox->pack_start (*beforeIarea);
 2185 
 2186         afterLabel = Gtk::manage (new Gtk::Label ());
 2187         afterLabel->set_markup (Glib::ustring ("<b>") + M ("GENERAL_AFTER") + "</b>");
 2188         afterHeaderBox = Gtk::manage (new Gtk::Box (Gtk::ORIENTATION_HORIZONTAL));
 2189         afterHeaderBox->set_size_request (0, HeaderBoxHeight);
 2190         afterHeaderBox->pack_end (*afterLabel, Gtk::PACK_SHRINK, 2);
 2191         afterBox->pack_start (*afterHeaderBox, Gtk::PACK_SHRINK, 2);
 2192         afterBox->reorder_child (*afterHeaderBox, 0);
 2193 
 2194         beforeAfterBox->pack_start (*beforeBox);
 2195         beforeAfterBox->reorder_child (*beforeBox, 0);
 2196         beforeAfterBox->show_all ();
 2197 
 2198         beforePreviewHandler = new PreviewHandler ();
 2199 
 2200         beforeIpc = rtengine::StagedImageProcessor::create (beforeImg);
 2201         beforeIpc->setPreviewScale (10);
 2202         beforeIpc->setPreviewImageListener (beforePreviewHandler);
 2203         Glib::ustring monitorProfile;
 2204         rtengine::RenderingIntent intent;
 2205         ipc->getMonitorProfile(monitorProfile, intent);
 2206         beforeIpc->setMonitorProfile(monitorProfile, intent);
 2207 
 2208         beforeIarea->imageArea->setPreviewHandler (beforePreviewHandler);
 2209         beforeIarea->imageArea->setImProcCoordinator (beforeIpc);
 2210 
 2211         beforeIarea->imageArea->setPreviewModePanel (iareapanel->imageArea->previewModePanel);
 2212         beforeIarea->imageArea->setIndicateClippedPanel (iareapanel->imageArea->indClippedPanel);
 2213         iareapanel->imageArea->iLinkedImageArea = beforeIarea->imageArea;
 2214 
 2215         iareapanel->setBeforeAfterViews (beforeIarea, iareapanel);
 2216         beforeIarea->setBeforeAfterViews (beforeIarea, iareapanel);
 2217 
 2218         rtengine::procparams::ProcParams params;
 2219 
 2220         if (history->getBeforeLineParams (params)) {
 2221             historyBeforeLineChanged (params);
 2222         }
 2223     }
 2224 }
 2225 
 2226 void EditorPanel::tbBeforeLock_toggled ()
 2227 {
 2228     history->blistenerLock = tbBeforeLock->get_active();
 2229     tbBeforeLock->get_active() ? tbBeforeLock->set_image (*iBeforeLockON) : tbBeforeLock->set_image (*iBeforeLockOFF);
 2230 }
 2231 
 2232 void EditorPanel::histogramChanged(
 2233     const LUTu& histRed,
 2234     const LUTu& histGreen,
 2235     const LUTu& histBlue,
 2236     const LUTu& histLuma,
 2237     const LUTu& histToneCurve,
 2238     const LUTu& histLCurve,
 2239     const LUTu& histCCurve,
 2240     const LUTu& histLCAM,
 2241     const LUTu& histCCAM,
 2242     const LUTu& histRedRaw,
 2243     const LUTu& histGreenRaw,
 2244     const LUTu& histBlueRaw,
 2245     const LUTu& histChroma,
 2246     const LUTu& histLRETI
 2247 )
 2248 {
 2249     if (histogramPanel) {
 2250         histogramPanel->histogramChanged(histRed, histGreen, histBlue, histLuma, histChroma, histRedRaw, histGreenRaw, histBlueRaw);
 2251     }
 2252 
 2253     tpc->updateCurveBackgroundHistogram(histToneCurve, histLCurve, histCCurve, histLCAM, histCCAM, histRed, histGreen, histBlue, histLuma, histLRETI);
 2254 }
 2255 
 2256 bool EditorPanel::CheckSidePanelsVisibility()
 2257 {
 2258     if (tbTopPanel_1) {
 2259         return tbTopPanel_1->get_active() || tbRightPanel_1->get_active() || hidehp->get_active();
 2260     }
 2261 
 2262     return tbRightPanel_1->get_active() || hidehp->get_active();
 2263 }
 2264 
 2265 void EditorPanel::toggleSidePanels()
 2266 {
 2267     // Maximize preview panel:
 2268     // toggle top AND right AND history panels
 2269 
 2270     bool bAllSidePanelsVisible;
 2271     bAllSidePanelsVisible = CheckSidePanelsVisibility();
 2272 
 2273     if (tbTopPanel_1) {
 2274         tbTopPanel_1->set_active (!bAllSidePanelsVisible);
 2275     }
 2276 
 2277     tbRightPanel_1->set_active (!bAllSidePanelsVisible);
 2278     hidehp->set_active (!bAllSidePanelsVisible);
 2279 
 2280     if (!bAllSidePanelsVisible) {
 2281         tbShowHideSidePanels->set_image (*iShowHideSidePanels);
 2282     } else {
 2283         tbShowHideSidePanels->set_image (*iShowHideSidePanels_exit);
 2284     }
 2285 }
 2286 
 2287 void EditorPanel::toggleSidePanelsZoomFit()
 2288 {
 2289     toggleSidePanels();
 2290 
 2291     // fit image preview
 2292     // !!! TODO this does not want to work... seems to have an effect on a subsequent key press
 2293     // iarea->imageArea->zoomPanel->zoomFitClicked();
 2294 }
 2295 
 2296 void EditorPanel::tbShowHideSidePanels_managestate()
 2297 {
 2298     bool bAllSidePanelsVisible;
 2299     bAllSidePanelsVisible = CheckSidePanelsVisibility();
 2300     ShowHideSidePanelsconn.block (true);
 2301 
 2302     tbShowHideSidePanels->set_active (!bAllSidePanelsVisible);
 2303 
 2304     ShowHideSidePanelsconn.block (false);
 2305 }
 2306 
 2307 void EditorPanel::updateProfiles (const Glib::ustring &printerProfile, rtengine::RenderingIntent printerIntent, bool printerBPC)
 2308 {
 2309 }
 2310 
 2311 void EditorPanel::updateTPVScrollbar (bool hide)
 2312 {
 2313     tpc->updateTPVScrollbar (hide);
 2314 }
 2315 
 2316 void EditorPanel::updateHistogramPosition (int oldPosition, int newPosition)
 2317 {
 2318 
 2319     switch (newPosition) {
 2320         case 0:
 2321 
 2322             // No histogram
 2323             if (!oldPosition) {
 2324                 // An histogram actually exist, we delete it
 2325                 delete histogramPanel;
 2326                 histogramPanel = nullptr;
 2327             }
 2328 
 2329             // else no need to create it
 2330             break;
 2331 
 2332         case 1:
 2333 
 2334             // Histogram on the left pane
 2335             if (oldPosition == 0) {
 2336                 // There was no Histogram before, so we create it
 2337                 histogramPanel = Gtk::manage (new HistogramPanel ());
 2338                 leftbox->pack1(*histogramPanel, false, false);
 2339             } else if (oldPosition == 2) {
 2340                 // The histogram was on the right side, so we move it to the left
 2341                 histogramPanel->reference();
 2342                 removeIfThere (vboxright, histogramPanel, false);
 2343                 leftbox->pack1(*histogramPanel, false, false);
 2344                 histogramPanel->unreference();
 2345             }
 2346 
 2347             leftbox->set_position(options.histogramHeight);
 2348             histogramPanel->reorder (Gtk::POS_LEFT);
 2349             break;
 2350 
 2351         case 2:
 2352         default:
 2353 
 2354             // Histogram on the right pane
 2355             if (oldPosition == 0) {
 2356                 // There was no Histogram before, so we create it
 2357                 histogramPanel = Gtk::manage (new HistogramPanel ());
 2358                 vboxright->pack1 (*histogramPanel, false, false);
 2359             } else if (oldPosition == 1) {
 2360                 // The histogram was on the left side, so we move it to the right
 2361                 histogramPanel->reference();
 2362                 removeIfThere (leftbox, histogramPanel, false);
 2363                 vboxright->pack1 (*histogramPanel, false, false);
 2364                 histogramPanel->unreference();
 2365             }
 2366 
 2367             vboxright->set_position(options.histogramHeight);
 2368             histogramPanel->reorder (Gtk::POS_RIGHT);
 2369             break;
 2370     }
 2371 
 2372     iareapanel->imageArea->setPointerMotionHListener (histogramPanel);
 2373 
 2374 }
 2375 
 2376 
 2377 void EditorPanel::defaultMonitorProfileChanged (const Glib::ustring &profile_name, bool auto_monitor_profile)
 2378 {
 2379     colorMgmtToolBar->defaultMonitorProfileChanged (profile_name, auto_monitor_profile);
 2380 }
 2381