rawTherapee/rtgui/editorpanel.cc
2017-06-24 16:38:34 +02:00

2250 lines
74 KiB
C++

/*
* This file is part of RawTherapee.
*
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
* Copyright (c) 2010 Oliver Duis <www.oliverduis.de>
*
* RawTherapee is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* RawTherapee is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
*/
#include "editorpanel.h"
#include <iostream>
#include "../rtengine/imagesource.h"
#include "../rtengine/iccstore.h"
#include "soundman.h"
#include "rtimage.h"
#include "rtwindow.h"
#include "guiutils.h"
#include "popupbutton.h"
#include "options.h"
#include "progressconnector.h"
#include "procparamchangers.h"
#include "placesbrowser.h"
using namespace rtengine::procparams;
namespace
{
struct spparams {
double val;
Glib::ustring str;
MyProgressBar *pProgress;
Glib::RefPtr<Gtk::CssProvider> cssProvider;
};
int setprogressStrUI ( void *p )
{
spparams *s = static_cast<spparams*> (p);
if ( ! s->str.empty() ) {
s->pProgress->set_text ( M (s->str) );
}
if ( s->val >= 0 ) {
s->pProgress->set_fraction ( s->val );
if (s->cssProvider) {
if ( s->val < 1.0 ) {
s->cssProvider->load_from_data ("ProgressBar { background-color: red }");
} else {
s->cssProvider->load_from_data ("ProgressBar { background-color: grey }");
}
s->pProgress->get_style_context()->set_background (s->pProgress->get_window());
}
}
delete s;
return FALSE;
}
bool find_default_monitor_profile(GdkWindow *rootwin, Glib::ustring &defprof, Glib::ustring &defprofname)
{
#ifdef WIN32
HDC hDC = GetDC(nullptr);
if (hDC != nullptr) {
if (SetICMMode(hDC, ICM_ON)) {
char profileName[MAX_PATH + 1];
DWORD profileLength = MAX_PATH;
if (GetICMProfileA(hDC, &profileLength, profileName)) {
defprof = Glib::ustring(profileName);
defprofname = Glib::path_get_basename(defprof);
size_t pos = defprofname.rfind(".");
if (pos != Glib::ustring::npos) {
defprofname = defprofname.substr(0, pos);
}
defprof = Glib::ustring("file:") + defprof;
return true;
}
// might fail if e.g. the monitor has no profile
}
ReleaseDC(NULL, hDC);
}
#elif !defined(__APPLE__)
// taken from geeqie (image.c) and adapted
// Originally licensed as GPL v2+, with the following copyright:
// * Copyright (C) 2006 John Ellis
// * Copyright (C) 2008 - 2016 The Geeqie Team
//
guchar *prof = nullptr;
gint proflen;
GdkAtom type = GDK_NONE;
gint format = 0;
if (gdk_property_get(rootwin, gdk_atom_intern("_ICC_PROFILE", FALSE), GDK_NONE, 0, 64 * 1024 * 1024, FALSE, &type, &format, &proflen, &prof) && proflen > 0) {
cmsHPROFILE p = cmsOpenProfileFromMem(prof, proflen);
if (p) {
defprofname = "from GDK";
defprof = Glib::build_filename(Options::rtdir, "GDK_ICC_PROFILE.icc");
if (cmsSaveProfileToFile(p, defprof.c_str())) {
cmsCloseProfile(p);
if (prof) {
g_free(prof);
}
defprof = Glib::ustring("file:") + defprof;
return true;
}
}
}
if (prof) {
g_free(prof);
}
#endif
return false;
}
}
class EditorPanel::ColorManagementToolbar
{
private:
#if !defined(__APPLE__) // monitor profile not supported on apple
MyComboBoxText profileBox;
#endif
PopUpButton intentBox;
Gtk::ToggleButton softProof;
Gtk::ToggleButton spGamutCheck;
sigc::connection profileConn, intentConn, softproofConn;
bool canSProof;
Glib::ustring defprof;
rtengine::StagedImageProcessor* const& processor;
private:
#if !defined(__APPLE__) // monitor profile not supported on apple
void prepareProfileBox ()
{
profileBox.setPreferredWidth(70, 200);
setExpandAlignProperties (&profileBox, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_FILL);
profileBox.append (M ("PREFERENCES_PROFILE_NONE"));
Glib::ustring defprofname;
if (find_default_monitor_profile(profileBox.get_root_window()->gobj(), defprof, defprofname)) {
profileBox.append (M ("MONITOR_PROFILE_SYSTEM") + " (" + defprofname + ")");
if (options.rtSettings.autoMonitorProfile) {
rtengine::ICCStore::getInstance()->setDefaultMonitorProfileName(defprof);
profileBox.set_active(1);
} else {
profileBox.set_active(0);
}
} else {
profileBox.set_active (0);
}
const std::vector<Glib::ustring> profiles = rtengine::ICCStore::getInstance()->getProfiles (rtengine::ICCStore::ProfileType::MONITOR);
for (const auto profile: profiles) {
profileBox.append (profile);
}
profileBox.set_tooltip_text (profileBox.get_active_text ());
}
#endif
void prepareIntentBox ()
{
// same order as the enum
intentBox.addEntry ("intent-perceptual.png", M ("PREFERENCES_INTENT_PERCEPTUAL"));
intentBox.addEntry("intent-relative.png", M("PREFERENCES_INTENT_RELATIVE"));
intentBox.addEntry ("intent-absolute.png", M ("PREFERENCES_INTENT_ABSOLUTE"));
setExpandAlignProperties (intentBox.buttonGroup, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_FILL);
intentBox.setSelected(1);
intentBox.show ();
}
void prepareSoftProofingBox ()
{
Gtk::Image *softProofImage = Gtk::manage (new RTImage ("softProof.png"));
softProofImage->set_padding(0, 0);
softProof.add(*softProofImage);
softProof.set_relief(Gtk::RELIEF_NONE);
softProof.set_tooltip_markup(M("SOFTPROOF_TOOLTIP"));
softProof.set_active(false);
softProof.set_sensitive(canSProof);
softProof.show ();
Gtk::Image *spGamutCheckImage = Gtk::manage (new RTImage ("spGamutCheck.png"));
spGamutCheckImage->set_padding(0, 0);
spGamutCheck.add(*spGamutCheckImage);
spGamutCheck.set_relief(Gtk::RELIEF_NONE);
spGamutCheck.set_tooltip_markup(M("SOFTPROOF_GAMUTCHECK_TOOLTIP"));
spGamutCheck.set_active(false);
spGamutCheck.set_sensitive(false);
spGamutCheck.show ();
}
#if !defined(__APPLE__)
void profileBoxChanged ()
{
updateParameters ();
}
#endif
void intentBoxChanged (int)
{
updateParameters ();
}
void softProofToggled ()
{
updateSoftProofParameters ();
}
void spGamutCheckToggled ()
{
updateSoftProofParameters ();
}
void updateParameters (bool noEvent = false)
{
#if !defined(__APPLE__) // monitor profile not supported on apple
ConnectionBlocker profileBlocker (profileConn);
#endif
ConnectionBlocker intentBlocker (intentConn);
Glib::ustring profile;
#if !defined(__APPLE__) // monitor profile not supported on apple
if (!defprof.empty() && profileBox.get_active_row_number () == 1) {
profile = defprof;
if (profile.empty ()) {
profile = options.rtSettings.monitorProfile;
}
if (profile.empty ()) {
profile = "sRGB IEC61966-2.1";
}
} else if (profileBox.get_active_row_number () > 0) {
profile = profileBox.get_active_text ();
}
#else
profile = "RT_sRGB";
#endif
#if !defined(__APPLE__) // monitor profile not supported on apple
if (profileBox.get_active_row_number () == 0) {
profile.clear ();
intentBox.set_sensitive (false);
intentBox.setSelected (1);
softProof.set_sensitive(false);
spGamutCheck.set_sensitive(false);
profileBox.set_tooltip_text ("");
} else {
const uint8_t supportedIntents = rtengine::ICCStore::getInstance()->getProofIntents (profile);
const bool supportsRelativeColorimetric = supportedIntents & 1 << INTENT_RELATIVE_COLORIMETRIC;
const bool supportsPerceptual = supportedIntents & 1 << INTENT_PERCEPTUAL;
const bool supportsAbsoluteColorimetric = supportedIntents & 1 << INTENT_ABSOLUTE_COLORIMETRIC;
if (supportsPerceptual || supportsRelativeColorimetric || supportsAbsoluteColorimetric) {
intentBox.set_sensitive (true);
intentBox.setItemSensitivity(0, supportsPerceptual);
intentBox.setItemSensitivity(1, supportsRelativeColorimetric);
intentBox.setItemSensitivity(2, supportsAbsoluteColorimetric);
softProof.set_sensitive(canSProof);
spGamutCheck.set_sensitive(canSProof);
} else {
intentBox.setItemSensitivity(0, true);
intentBox.setItemSensitivity(1, true);
intentBox.setItemSensitivity(2, true);
intentBox.set_sensitive (false);
intentBox.setSelected (1);
softProof.set_sensitive(false);
spGamutCheck.set_sensitive(false);
}
profileBox.set_tooltip_text (profileBox.get_active_text ());
}
#endif
rtengine::RenderingIntent intent;
switch (intentBox.getSelected ()) {
default:
case 0:
intent = rtengine::RI_PERCEPTUAL;
break;
case 1:
intent = rtengine::RI_RELATIVE;
break;
case 2:
intent = rtengine::RI_ABSOLUTE;
break;
}
if (!processor) {
return;
}
if (!noEvent) {
processor->beginUpdateParams ();
}
processor->setMonitorProfile (profile, intent);
processor->setSoftProofing (softProof.get_sensitive() && softProof.get_active(), spGamutCheck.get_sensitive() && spGamutCheck.get_active());
if (!noEvent) {
processor->endUpdateParams (rtengine::EvMonitorTransform);
}
}
void updateSoftProofParameters (bool noEvent = false)
{
if (!canSProof) {
ConnectionBlocker profileBlocker (softproofConn);
softProof.set_active(false);
softProof.set_sensitive(false);
#if !defined(__APPLE__) // monitor profile not supported on apple
} else {
softProof.set_sensitive(profileBox.get_active_row_number () > 0);
#endif
}
spGamutCheck.set_sensitive(softProof.get_sensitive() && softProof.get_active());
#if !defined(__APPLE__) // monitor profile not supported on apple
if (profileBox.get_active_row_number () > 0) {
#endif
if (processor) {
if (!noEvent) {
processor->beginUpdateParams ();
}
processor->setSoftProofing (softProof.get_sensitive() && softProof.get_active(), spGamutCheck.get_sensitive() && spGamutCheck.get_active());
if (!noEvent) {
processor->endUpdateParams (rtengine::EvMonitorTransform);
}
}
#if !defined(__APPLE__) // monitor profile not supported on apple
}
#endif
}
public:
explicit ColorManagementToolbar (rtengine::StagedImageProcessor* const& ipc) :
intentBox (Glib::ustring (), true),
canSProof(!options.rtSettings.printerProfile.empty() && options.rtSettings.printerProfile != "None"), // assuming the printer profile exist!
processor (ipc)
{
#if !defined(__APPLE__) // monitor profile not supported on apple
prepareProfileBox ();
#endif
prepareIntentBox ();
prepareSoftProofingBox ();
reset ();
softproofConn = softProof.signal_toggled().connect(sigc::mem_fun (this, &ColorManagementToolbar::softProofToggled));
spGamutCheck.signal_toggled().connect(sigc::mem_fun (this, &ColorManagementToolbar::spGamutCheckToggled));
#if !defined(__APPLE__) // monitor profile not supported on apple
profileConn = profileBox.signal_changed ().connect (sigc::mem_fun (this, &ColorManagementToolbar::profileBoxChanged));
#endif
intentConn = intentBox.signal_changed ().connect (sigc::mem_fun (this, &ColorManagementToolbar::intentBoxChanged));
}
void pack_right_in (Gtk::Grid* grid)
{
#if !defined(__APPLE__) // monitor profile not supported on apple
grid->attach_next_to (profileBox, Gtk::POS_RIGHT, 1, 1);
#endif
grid->attach_next_to (*intentBox.buttonGroup, Gtk::POS_RIGHT, 1, 1);
grid->attach_next_to (softProof, Gtk::POS_RIGHT, 1, 1);
grid->attach_next_to (spGamutCheck, Gtk::POS_RIGHT, 1, 1);
}
void canSoftProof(bool canSP)
{
canSProof = canSP;
updateSoftProofParameters();
}
void updateProcessor()
{
if (processor) {
updateParameters(true);
}
}
void reset ()
{
ConnectionBlocker intentBlocker (intentConn);
#if !defined(__APPLE__) // monitor profile not supported on apple
ConnectionBlocker profileBlocker (profileConn);
if (!defprof.empty() && options.rtSettings.autoMonitorProfile) {
profileBox.set_active(1);
} else {
setActiveTextOrIndex (profileBox, options.rtSettings.monitorProfile, 0);
}
#endif
switch (options.rtSettings.monitorIntent) {
default:
case rtengine::RI_PERCEPTUAL:
intentBox.setSelected (0);
break;
case rtengine::RI_RELATIVE:
intentBox.setSelected (1);
break;
case rtengine::RI_ABSOLUTE:
intentBox.setSelected (2);
break;
}
updateParameters ();
}
void defaultMonitorProfileChanged(const Glib::ustring &profile_name, bool auto_monitor_profile)
{
ConnectionBlocker profileBlocker (profileConn);
if (auto_monitor_profile && !defprof.empty()) {
rtengine::ICCStore::getInstance()->setDefaultMonitorProfileName(defprof);
#ifndef __APPLE__
profileBox.set_active(1);
#endif
} else {
rtengine::ICCStore::getInstance()->setDefaultMonitorProfileName(profile_name);
#ifndef __APPLE__
setActiveTextOrIndex(profileBox, profile_name, 0);
#endif
}
}
};
EditorPanel::EditorPanel (FilePanel* filePanel)
: catalogPane(nullptr), realized(false), tbBeforeLock(nullptr), iHistoryShow(nullptr), iHistoryHide(nullptr), iTopPanel_1_Show(nullptr), iTopPanel_1_Hide(nullptr), iRightPanel_1_Show(nullptr), iRightPanel_1_Hide(nullptr), iBeforeLockON(nullptr), iBeforeLockOFF(nullptr), previewHandler(nullptr), beforePreviewHandler(nullptr), beforeIarea(nullptr), beforeBox(nullptr), afterBox(nullptr), beforeLabel(nullptr), afterLabel(nullptr), beforeHeaderBox(nullptr), afterHeaderBox(nullptr), parent(nullptr), openThm(nullptr), isrc(nullptr), ipc(nullptr), beforeIpc(nullptr), err(0), isProcessing(false)
{
epih = new EditorPanelIdleHelper;
epih->epanel = this;
epih->destroyed = false;
epih->pending = 0;
//rtengine::befaf=true;
processingStartedTime = 0;
firstProcessingDone = false;
// construct toolpanelcoordinator
tpc = new ToolPanelCoordinator ();
// build GUI
// build left side panel
leftbox = new Gtk::VBox ();
leftbox->set_size_request (230, 250);
histogramPanel = nullptr;
profilep = Gtk::manage (new ProfilePanel ());
ppframe = new Gtk::Frame ();
ppframe->set_name("ProfilePanel");
ppframe->add (*profilep);
ppframe->set_label (M ("PROFILEPANEL_LABEL"));
//leftbox->pack_start (*ppframe, Gtk::PACK_SHRINK, 4);
navigator = Gtk::manage (new Navigator ());
navigator->previewWindow->set_size_request (-1, 150);
leftbox->pack_start (*navigator, Gtk::PACK_SHRINK, 2);
history = Gtk::manage (new History ());
leftbox->pack_start (*history);
leftbox->show_all ();
// build the middle of the screen
Gtk::VBox* editbox = Gtk::manage (new Gtk::VBox ());
info = Gtk::manage (new Gtk::ToggleButton ());
Gtk::Image* infoimg = Gtk::manage (new RTImage ("info.png"));
info->add (*infoimg);
info->set_relief (Gtk::RELIEF_NONE);
info->set_tooltip_markup (M ("MAIN_TOOLTIP_QINFO"));
beforeAfter = Gtk::manage (new Gtk::ToggleButton ());
Gtk::Image* beforeAfterIcon = Gtk::manage (new RTImage ("beforeafter.png"));
beforeAfter->add (*beforeAfterIcon);
beforeAfter->set_relief (Gtk::RELIEF_NONE);
beforeAfter->set_tooltip_markup (M ("MAIN_TOOLTIP_TOGGLE"));
iBeforeLockON = new RTImage ("lock-on.png");
iBeforeLockOFF = new RTImage ("lock-off.png");
Gtk::VSeparator* vsept = Gtk::manage (new Gtk::VSeparator ());
Gtk::VSeparator* vsepz = Gtk::manage (new Gtk::VSeparator ());
Gtk::VSeparator* vsepi = Gtk::manage (new Gtk::VSeparator ());
Gtk::VSeparator* vseph = Gtk::manage (new Gtk::VSeparator ());
hidehp = Gtk::manage (new Gtk::ToggleButton ());
iHistoryShow = new RTImage ("panel-to-right.png");
iHistoryHide = new RTImage ("panel-to-left.png");
hidehp->set_relief (Gtk::RELIEF_NONE);
hidehp->set_active (options.showHistory);
hidehp->set_tooltip_markup (M ("MAIN_TOOLTIP_HIDEHP"));
if (options.showHistory) {
hidehp->set_image (*iHistoryHide);
} else {
hidehp->set_image (*iHistoryShow);
}
tbTopPanel_1 = nullptr;
if (!simpleEditor && filePanel) {
tbTopPanel_1 = new Gtk::ToggleButton ();
iTopPanel_1_Show = new RTImage ("panel-to-bottom.png");
iTopPanel_1_Hide = new RTImage ("panel-to-top.png");
tbTopPanel_1->set_relief (Gtk::RELIEF_NONE);
tbTopPanel_1->set_active (true);
tbTopPanel_1->set_tooltip_markup (M ("MAIN_TOOLTIP_SHOWHIDETP1"));
tbTopPanel_1->set_image (*iTopPanel_1_Hide);
}
Gtk::VSeparator* vsepcl = Gtk::manage (new Gtk::VSeparator ());
Gtk::VSeparator* vsepz2 = Gtk::manage (new Gtk::VSeparator ());
Gtk::VSeparator* vsepz3 = Gtk::manage (new Gtk::VSeparator ());
Gtk::VSeparator* vsepz4 = Gtk::manage (new Gtk::VSeparator ());
Gtk::VSeparator* vsep1 = Gtk::manage (new Gtk::VSeparator ());
Gtk::VSeparator* vsep2 = Gtk::manage (new Gtk::VSeparator ());
iareapanel = new ImageAreaPanel ();
tpc->setEditProvider (iareapanel->imageArea);
tpc->getToolBar()->setLockablePickerToolListener(iareapanel->imageArea);
Gtk::HBox* toolBarPanel = Gtk::manage (new Gtk::HBox ());
toolBarPanel->set_name ("EditorTopPanel");
toolBarPanel->pack_start (*hidehp, Gtk::PACK_SHRINK, 1);
toolBarPanel->pack_start (*vseph, Gtk::PACK_SHRINK, 2);
toolBarPanel->pack_start (*info, Gtk::PACK_SHRINK, 1);
toolBarPanel->pack_start (*beforeAfter, Gtk::PACK_SHRINK, 1);
toolBarPanel->pack_start (*vsepi, Gtk::PACK_SHRINK, 2);
toolBarPanel->pack_start (*tpc->getToolBar(), Gtk::PACK_SHRINK, 1);
toolBarPanel->pack_start (*vsept, Gtk::PACK_SHRINK, 2);
if (tbTopPanel_1) {
Gtk::VSeparator* vsep = Gtk::manage (new Gtk::VSeparator ());
toolBarPanel->pack_end (*tbTopPanel_1, Gtk::PACK_SHRINK, 1);
toolBarPanel->pack_end (*vsep, Gtk::PACK_SHRINK, 2);
}
toolBarPanel->pack_end (*tpc->coarse, Gtk::PACK_SHRINK, 2);
toolBarPanel->pack_end (*vsepcl, Gtk::PACK_SHRINK, 2);
toolBarPanel->pack_end (*iareapanel->imageArea->indClippedPanel, Gtk::PACK_SHRINK, 0);
toolBarPanel->pack_end (*vsepz, Gtk::PACK_SHRINK, 2);
toolBarPanel->pack_end (*iareapanel->imageArea->previewModePanel, Gtk::PACK_SHRINK, 0);
toolBarPanel->pack_end (*vsepz4, Gtk::PACK_SHRINK, 2);
afterBox = Gtk::manage (new Gtk::VBox ());
afterBox->pack_start (*iareapanel);
beforeAfterBox = Gtk::manage (new Gtk::HBox());
beforeAfterBox->set_name("BeforeAfterContainer");
beforeAfterBox->pack_start (*afterBox);
editbox->pack_start (*toolBarPanel, Gtk::PACK_SHRINK, 2);
editbox->pack_start (*beforeAfterBox);
// build right side panel
vboxright = new Gtk::VBox (false, 0);
vboxright->set_size_request (300, 250);
vboxright->pack_start (*ppframe, Gtk::PACK_SHRINK, 2);
// main notebook
vboxright->pack_start (*tpc->toolPanelNotebook);
// Save buttons
Gtk::Grid *iops = new Gtk::Grid ();
iops->set_name ("IopsPanel");
iops->set_orientation (Gtk::ORIENTATION_HORIZONTAL);
iops->set_row_spacing (2);
iops->set_column_spacing (2);
Gtk::Image *saveButtonImage = Gtk::manage (new RTImage ("gtk-save-large.png"));
saveimgas = Gtk::manage (new Gtk::Button ());
saveimgas->add (*saveButtonImage);
saveimgas->set_tooltip_markup (M ("MAIN_BUTTON_SAVE_TOOLTIP"));
setExpandAlignProperties (saveimgas, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_FILL);
Gtk::Image *queueButtonImage = Gtk::manage (new RTImage ("processing.png"));
queueimg = Gtk::manage (new Gtk::Button ());
queueimg->add (*queueButtonImage);
queueimg->set_tooltip_markup (M ("MAIN_BUTTON_PUTTOQUEUE_TOOLTIP"));
setExpandAlignProperties (queueimg, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_FILL);
Gtk::Image *sendToEditorButtonImage = Gtk::manage (new RTImage ("image-editor.png"));
sendtogimp = Gtk::manage (new Gtk::Button ());
sendtogimp->add (*sendToEditorButtonImage);
sendtogimp->set_tooltip_markup (M ("MAIN_BUTTON_SENDTOEDITOR_TOOLTIP"));
setExpandAlignProperties (sendtogimp, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_FILL);
// Status box
progressLabel = Gtk::manage (new MyProgressBar (300));
progressLabel->set_show_text (true);
setExpandAlignProperties (progressLabel, true, false, Gtk::ALIGN_START, Gtk::ALIGN_FILL);
progressLabel->set_fraction (0.0);
// tbRightPanel_1
tbRightPanel_1 = new Gtk::ToggleButton ();
iRightPanel_1_Show = new RTImage ("panel-to-left.png");
iRightPanel_1_Hide = new RTImage ("panel-to-right.png");
tbRightPanel_1->set_relief (Gtk::RELIEF_NONE);
tbRightPanel_1->set_active (true);
tbRightPanel_1->set_tooltip_markup (M ("MAIN_TOOLTIP_SHOWHIDERP1"));
tbRightPanel_1->set_image (*iRightPanel_1_Hide);
setExpandAlignProperties (tbRightPanel_1, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_FILL);
// ShowHideSidePanels
tbShowHideSidePanels = new Gtk::ToggleButton ();
iShowHideSidePanels = new RTImage ("crossed-arrows-out.png");
iShowHideSidePanels_exit = new RTImage ("crossed-arrows-in.png");
tbShowHideSidePanels->set_relief (Gtk::RELIEF_NONE);
tbShowHideSidePanels->set_active (false);
tbShowHideSidePanels->set_tooltip_markup (M ("MAIN_BUTTON_SHOWHIDESIDEPANELS_TOOLTIP"));
tbShowHideSidePanels->set_image (*iShowHideSidePanels);
setExpandAlignProperties (tbShowHideSidePanels, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_FILL);
navPrev = navNext = navSync = nullptr;
if (!simpleEditor && !options.tabbedUI) {
// Navigation buttons
Gtk::Image *navPrevImage = Gtk::manage (new RTImage ("nav-prev.png"));
navPrevImage->set_padding (0, 0);
navPrev = Gtk::manage (new Gtk::Button ());
navPrev->add (*navPrevImage);
navPrev->set_relief (Gtk::RELIEF_NONE);
navPrev->set_tooltip_markup (M ("MAIN_BUTTON_NAVPREV_TOOLTIP"));
setExpandAlignProperties (navPrev, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_FILL);
Gtk::Image *navNextImage = Gtk::manage (new RTImage ("nav-next.png"));
navNextImage->set_padding (0, 0);
navNext = Gtk::manage (new Gtk::Button ());
navNext->add (*navNextImage);
navNext->set_relief (Gtk::RELIEF_NONE);
navNext->set_tooltip_markup (M ("MAIN_BUTTON_NAVNEXT_TOOLTIP"));
setExpandAlignProperties (navNext, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_FILL);
Gtk::Image *navSyncImage = Gtk::manage (new RTImage ("nav-sync.png"));
navSyncImage->set_padding (0, 0);
navSync = Gtk::manage (new Gtk::Button ());
navSync->add (*navSyncImage);
navSync->set_relief (Gtk::RELIEF_NONE);
navSync->set_tooltip_markup (M ("MAIN_BUTTON_NAVSYNC_TOOLTIP"));
setExpandAlignProperties (navSync, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_FILL);
}
// ================== PACKING THE BOTTOM WIDGETS =================
// Adding widgets from center to the left, on the left side (using Gtk::POS_LEFT)
iops->attach_next_to (*vsep2, Gtk::POS_LEFT, 1, 1);
iops->attach_next_to (*progressLabel, Gtk::POS_LEFT, 1, 1);
iops->attach_next_to (*vsep1, Gtk::POS_LEFT, 1, 1);
iops->attach_next_to (*sendtogimp, Gtk::POS_LEFT, 1, 1);
if (!simpleEditor) {
iops->attach_next_to (*queueimg, Gtk::POS_LEFT, 1, 1);
}
iops->attach_next_to (*saveimgas, Gtk::POS_LEFT, 1, 1);
// Color management toolbar
colorMgmtToolBar.reset (new ColorManagementToolbar (ipc));
colorMgmtToolBar->pack_right_in (iops);
if (!simpleEditor && !options.tabbedUI) {
Gtk::VSeparator* vsep3 = Gtk::manage (new Gtk::VSeparator ());
iops->attach_next_to (*vsep3, Gtk::POS_RIGHT, 1, 1);
iops->attach_next_to (*navPrev, Gtk::POS_RIGHT, 1, 1);
iops->attach_next_to (*navSync, Gtk::POS_RIGHT, 1, 1);
iops->attach_next_to (*navNext, Gtk::POS_RIGHT, 1, 1);
}
iops->attach_next_to (*vsepz2, Gtk::POS_RIGHT, 1, 1);
iops->attach_next_to (*iareapanel->imageArea->zoomPanel, Gtk::POS_RIGHT, 1, 1);
iops->attach_next_to (*vsepz3, Gtk::POS_RIGHT, 1, 1);
iops->attach_next_to (*tbShowHideSidePanels, Gtk::POS_RIGHT, 1, 1);
iops->attach_next_to (*tbRightPanel_1, Gtk::POS_RIGHT, 1, 1);
editbox->pack_start (*iops, Gtk::PACK_SHRINK, 0);
editbox->show_all ();
// build screen
hpanedl = Gtk::manage (new Gtk::Paned(Gtk::ORIENTATION_HORIZONTAL));
hpanedl->set_name("EditorLeftPaned");
hpanedr = Gtk::manage (new Gtk::Paned(Gtk::ORIENTATION_HORIZONTAL));
hpanedr->set_name("EditorRightPaned");
leftbox->reference ();
vboxright->reference ();
if (options.showHistory) {
hpanedl->pack1 (*leftbox, false, false);
hpanedl->set_position (options.historyPanelWidth);
}
Gtk::VPaned * viewpaned = Gtk::manage (new Gtk::VPaned());
fPanel = filePanel;
if (filePanel) {
catalogPane = new Gtk::Paned();
viewpaned->pack1 (*catalogPane, false, true);
}
viewpaned->pack2 (*editbox, true, true);
hpanedl->pack2 (*viewpaned, true, true);
hpanedr->pack1 (*hpanedl, true, false);
hpanedr->pack2 (*vboxright, false, false);
hpanedl->signal_button_release_event().connect_notify ( sigc::mem_fun (*this, &EditorPanel::leftPaneButtonReleased) );
hpanedr->signal_button_release_event().connect_notify ( sigc::mem_fun (*this, &EditorPanel::rightPaneButtonReleased) );
pack_start (*hpanedr);
updateHistogramPosition (0, options.histogramPosition);
show_all ();
/*
// save as dialog
if (Glib::file_test (options.lastSaveAsPath, Glib::FILE_TEST_IS_DIR))
saveAsDialog = new SaveAsDialog (options.lastSaveAsPath);
else
saveAsDialog = new SaveAsDialog (safe_get_user_picture_dir());
saveAsDialog->set_default_size (options.saveAsDialogWidth, options.saveAsDialogHeight);
*/
// connect listeners
profilep->setProfileChangeListener (tpc);
history->setProfileChangeListener (tpc);
history->setHistoryBeforeLineListener (this);
tpc->addPParamsChangeListener (profilep);
tpc->addPParamsChangeListener (history);
tpc->addPParamsChangeListener (this);
iareapanel->imageArea->setCropGUIListener (tpc->getCropGUIListener());
iareapanel->imageArea->setPointerMotionListener (navigator);
iareapanel->imageArea->setImageAreaToolListener (tpc);
// initialize components
info->set_active (options.showInfo);
tpc->readOptions ();
// connect event handlers
info->signal_toggled().connect ( sigc::mem_fun (*this, &EditorPanel::info_toggled) );
beforeAfter->signal_toggled().connect ( sigc::mem_fun (*this, &EditorPanel::beforeAfterToggled) );
hidehp->signal_toggled().connect ( sigc::mem_fun (*this, &EditorPanel::hideHistoryActivated) );
tbRightPanel_1->signal_toggled().connect ( sigc::mem_fun (*this, &EditorPanel::tbRightPanel_1_toggled) );
saveimgas->signal_pressed().connect ( sigc::mem_fun (*this, &EditorPanel::saveAsPressed) );
queueimg->signal_pressed().connect ( sigc::mem_fun (*this, &EditorPanel::queueImgPressed) );
sendtogimp->signal_pressed().connect ( sigc::mem_fun (*this, &EditorPanel::sendToGimpPressed) );
if (navPrev) {
navPrev->signal_pressed().connect ( sigc::mem_fun (*this, &EditorPanel::openPreviousEditorImage) );
}
if (navNext) {
navNext->signal_pressed().connect ( sigc::mem_fun (*this, &EditorPanel::openNextEditorImage) );
}
if (navSync) {
navSync->signal_pressed().connect ( sigc::mem_fun (*this, &EditorPanel::syncFileBrowser) );
}
ShowHideSidePanelsconn = tbShowHideSidePanels->signal_toggled().connect ( sigc::mem_fun (*this, &EditorPanel::toggleSidePanels), true);
if (tbTopPanel_1) {
tbTopPanel_1->signal_toggled().connect ( sigc::mem_fun (*this, &EditorPanel::tbTopPanel_1_toggled) );
}
}
EditorPanel::~EditorPanel ()
{
idle_register.destroy();
history->setHistoryBeforeLineListener (nullptr);
// the order is important!
iareapanel->setBeforeAfterViews (nullptr, iareapanel);
delete iareapanel;
iareapanel = nullptr;
if (beforeIpc) {
beforeIpc->stopProcessing ();
}
delete beforeIarea;
beforeIarea = nullptr;
if (beforeIpc) {
beforeIpc->setPreviewImageListener (nullptr);
}
delete beforePreviewHandler;
beforePreviewHandler = nullptr;
if (beforeIpc) {
rtengine::StagedImageProcessor::destroy (beforeIpc);
}
beforeIpc = nullptr;
close ();
if (epih->pending) {
epih->destroyed = true;
} else {
delete epih;
}
delete tpc;
delete ppframe;
delete leftbox;
delete vboxright;
//delete saveAsDialog;
if (catalogPane) {
delete catalogPane;
}
if (iTopPanel_1_Show) {
delete iTopPanel_1_Show;
}
if (iTopPanel_1_Hide) {
delete iTopPanel_1_Hide;
}
if (iHistoryShow) {
delete iHistoryShow;
}
if (iHistoryHide) {
delete iHistoryHide;
}
if (iBeforeLockON) {
delete iBeforeLockON;
}
if (iBeforeLockOFF) {
delete iBeforeLockOFF;
}
if (iRightPanel_1_Show) {
delete iRightPanel_1_Show;
}
if (iRightPanel_1_Hide) {
delete iRightPanel_1_Hide;
}
}
void EditorPanel::leftPaneButtonReleased (GdkEventButton *event)
{
if (event->button == 1) {
// Button 1 released : it's a resize
options.historyPanelWidth = hpanedl->get_position();
}
/*else if (event->button == 3) {
}*/
}
void EditorPanel::rightPaneButtonReleased (GdkEventButton *event)
{
if (event->button == 1) {
int winW, winH;
parent->get_size (winW, winH);
// Button 1 released : it's a resize
options.toolPanelWidth = winW - hpanedr->get_position();
}
/*else if (event->button == 3) {
}*/
}
void EditorPanel::writeOptions()
{
if (profilep) {
profilep->writeOptions();
}
if (tpc) {
tpc->writeOptions();
}
}
void EditorPanel::showTopPanel (bool show)
{
if (tbTopPanel_1->get_active() != show) {
tbTopPanel_1->set_active (show);
}
}
void EditorPanel::setAspect ()
{
int winW, winH;
parent->get_size (winW, winH);
hpanedl->set_position (options.historyPanelWidth);
hpanedr->set_position (winW - options.toolPanelWidth);
// initialize components
if (info->get_active() != options.showInfo) {
info->set_active (options.showInfo);
}
}
void EditorPanel::on_realize ()
{
realized = true;
Gtk::VBox::on_realize ();
// This line is needed to avoid autoexpansion of the window :-/
//vboxright->set_size_request (options.toolPanelWidth, -1);
tpc->updateToolState();
}
void EditorPanel::open (Thumbnail* tmb, rtengine::InitialImage* isrc)
{
close();
isProcessing = true; // prevents closing-on-init
// initialize everything
openThm = tmb;
openThm->increaseRef ();
fname = openThm->getFileName();
lastSaveAsFileName = removeExtension (Glib::path_get_basename (fname));
previewHandler = new PreviewHandler ();
this->isrc = isrc;
ipc = rtengine::StagedImageProcessor::create (isrc);
ipc->setProgressListener (this);
colorMgmtToolBar->updateProcessor();
ipc->setPreviewImageListener (previewHandler);
ipc->setPreviewScale (10); // Important
tpc->initImage (ipc, tmb->getType() == FT_Raw);
ipc->setHistogramListener (this);
// iarea->fitZoom (); // tell to the editorPanel that the next image has to be fitted to the screen
iareapanel->imageArea->setPreviewHandler (previewHandler);
iareapanel->imageArea->setImProcCoordinator (ipc);
navigator->previewWindow->setPreviewHandler (previewHandler);
navigator->previewWindow->setImageArea (iareapanel->imageArea);
rtengine::ImageSource* is = isrc->getImageSource();
is->setProgressListener ( this );
// try to load the last saved parameters from the cache or from the paramfile file
ProcParams* ldprof = openThm->createProcParamsForUpdate (true, false); // will be freed by initProfile
// initialize profile
Glib::ustring defProf = openThm->getType() == FT_Raw ? options.defProfRaw : options.defProfImg;
profilep->initProfile (defProf, ldprof);
profilep->setInitialFileName (fname);
openThm->addThumbnailListener (this);
info_toggled ();
if (beforeIarea) {
beforeAfterToggled();
beforeAfterToggled();
}
// If in single tab mode, the main crop window is not constructed the very first time
// since there was no resize event
if (iareapanel->imageArea->mainCropWindow) {
iareapanel->imageArea->mainCropWindow->cropHandler.newImage (ipc, false);
iareapanel->imageArea->mainCropWindow->initialImageArrived();
// In single tab mode, the image is not always updated between switches
// normal redraw don't work, so this is the hard way
// Disabled this with Issue 2435 because it seems to work fine now
// if (!options.tabbedUI && iareapanel->imageArea->mainCropWindow->getZoomFitVal() == 1.0) {
// iareapanel->imageArea->mainCropWindow->cropHandler.update();
// }
} else {
Gtk::Allocation alloc;
iareapanel->imageArea->on_resized (alloc);
}
history->resetSnapShotNumber();
}
void EditorPanel::close ()
{
if (ipc) {
saveProfile ();
// close image processor and the current thumbnail
tpc->closeImage (); // this call stops image processing
tpc->writeOptions ();
rtengine::ImageSource* is = isrc->getImageSource();
is->setProgressListener( nullptr );
if (ipc) {
ipc->setPreviewImageListener (nullptr);
}
if (beforeIpc) {
beforeIpc->setPreviewImageListener (nullptr);
}
delete previewHandler;
previewHandler = nullptr;
if(iareapanel) {
iareapanel->imageArea->setPreviewHandler (nullptr);
iareapanel->imageArea->setImProcCoordinator (nullptr);
iareapanel->imageArea->unsubscribe();
}
rtengine::StagedImageProcessor::destroy (ipc);
ipc = nullptr;
navigator->previewWindow->setPreviewHandler (nullptr);
// If the file was deleted somewhere, the openThm.descreaseRef delete the object, but we don't know here
if (Glib::file_test(fname, Glib::FILE_TEST_EXISTS)) {
openThm->removeThumbnailListener (this);
openThm->decreaseRef ();
}
}
}
void EditorPanel::saveProfile ()
{
if (!ipc || !openThm) {
return;
}
// If the file was deleted, do not generate ghost entries
if (Glib::file_test(fname, Glib::FILE_TEST_EXISTS)) {
ProcParams params;
ipc->getParams (&params);
// Will call updateCache, which will update both the cached and sidecar files if necessary
openThm->setProcParams (params, nullptr, EDITOR);
}
}
Glib::ustring EditorPanel::getShortName ()
{
if (openThm) {
return Glib::path_get_basename (openThm->getFileName ());
} else {
return "";
}
}
Glib::ustring EditorPanel::getFileName ()
{
if (openThm) {
return openThm->getFileName ();
} else {
return "";
}
}
// TODO!!!
void EditorPanel::procParamsChanged (rtengine::procparams::ProcParams* params, rtengine::ProcEvent ev, Glib::ustring descr, ParamsEdited* paramsEdited)
{
// if (ev!=EvPhotoLoaded)
// saveLabel->set_markup (Glib::ustring("<span foreground=\"#AA0000\" weight=\"bold\">") + M("MAIN_BUTTON_SAVE") + "</span>");
}
void EditorPanel::setProgressState (bool inProcessing)
{
struct spsparams {
bool inProcessing;
EditorPanelIdleHelper* epih;
};
epih->pending++;
spsparams* p = new spsparams;
p->inProcessing = inProcessing;
p->epih = epih;
const auto func = [](gpointer data) -> gboolean {
spsparams* const p = static_cast<spsparams*>(data);
if (p->epih->destroyed) {
if (p->epih->pending == 1) {
delete p->epih;
} else {
p->epih->pending--;
}
delete p;
return 0;
}
p->epih->epanel->refreshProcessingState (p->inProcessing);
p->epih->pending--;
delete p;
return FALSE;
};
idle_register.add(func, p);
}
void EditorPanel::setProgress (double p)
{
spparams *s = new spparams;
s->val = p;
s->pProgress = progressLabel;
idle_register.add(setprogressStrUI, s);
}
void EditorPanel::setProgressStr (Glib::ustring str)
{
spparams *s = new spparams;
s->str = str;
s->val = -1;
s->pProgress = progressLabel;
idle_register.add(setprogressStrUI, s);
}
// This is only called from the ThreadUI, so within the gtk thread
void EditorPanel::refreshProcessingState (bool inProcessingP)
{
spparams *s = new spparams;
s->pProgress = progressLabel;
if (inProcessingP) {
if (processingStartedTime == 0) {
processingStartedTime = ::time(nullptr);
}
s->str = "PROGRESSBAR_PROCESSING";
s->val = 1.0;
} else {
// Set proc params of thumbnail. It saves it into the cache and updates the file browser.
if (ipc && openThm && tpc->getChangedState()) {
rtengine::procparams::ProcParams pparams;
ipc->getParams (&pparams);
openThm->setProcParams (pparams, nullptr, EDITOR, false);
}
// Ring a sound if it was a long event
if (processingStartedTime != 0) {
time_t curTime = ::time(nullptr);
if (::difftime (curTime, processingStartedTime) > options.sndLngEditProcDoneSecs) {
SoundManager::playSoundAsync (options.sndLngEditProcDone);
}
processingStartedTime = 0;
}
// Set progress bar "done"
s->str = "PROGRESSBAR_READY";
s->val = 0.0;
#ifdef WIN32
// Maybe accessing "parent", which is a Gtk object, can justify to get the Gtk lock...
if (!firstProcessingDone && static_cast<RTWindow*> (parent)->getIsFullscreen()) {
parent->fullscreen();
}
#endif
firstProcessingDone = true;
}
isProcessing = inProcessingP;
setprogressStrUI (s);
}
void EditorPanel::displayError (Glib::ustring title, Glib::ustring descr)
{
GtkWidget* msgd = gtk_message_dialog_new_with_markup (nullptr,
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_OK,
"<b>%s</b>",
descr.data());
gtk_window_set_title ((GtkWindow*)msgd, title.data());
g_signal_connect_swapped (msgd, "response",
G_CALLBACK (gtk_widget_destroy),
msgd);
gtk_widget_show_all (msgd);
}
void EditorPanel::error (Glib::ustring title, Glib::ustring descr)
{
struct errparams {
Glib::ustring descr;
Glib::ustring title;
EditorPanelIdleHelper* epih;
};
epih->pending++;
errparams* const p = new errparams;
p->descr = descr;
p->title = title;
p->epih = epih;
const auto func = [](gpointer data) -> gboolean {
errparams* const p = static_cast<errparams*> (data);
if (p->epih->destroyed) {
if (p->epih->pending == 1) {
delete p->epih;
} else {
p->epih->pending--;
}
delete p;
return 0;
}
p->epih->epanel->displayError (p->title, p->descr);
p->epih->pending--;
delete p;
return FALSE;
};
idle_register.add(func, p);
}
void EditorPanel::info_toggled ()
{
Glib::ustring infoString;
Glib::ustring infoString1; //1-st line
Glib::ustring infoString2; //2-nd line
Glib::ustring infoString3; //3-rd line
Glib::ustring infoString4; //4-th line
Glib::ustring expcomp;
if (!ipc || !openThm) {
return;
}
const rtengine::ImageMetaData* idata = ipc->getInitialImage()->getMetaData();
if (idata && idata->hasExif()) {
infoString1 = Glib::ustring::compose ("%1 + %2",
Glib::ustring (idata->getMake() + " " + idata->getModel()),
Glib::ustring (idata->getLens()));
infoString2 = Glib::ustring::compose ("<span size=\"small\">f/</span><span size=\"large\">%1</span> <span size=\"large\">%2</span><span size=\"small\">s</span> <span size=\"small\">%3</span><span size=\"large\">%4</span> <span size=\"large\">%5</span><span size=\"small\">mm</span>",
Glib::ustring (idata->apertureToString (idata->getFNumber())),
Glib::ustring (idata->shutterToString (idata->getShutterSpeed())),
M ("QINFO_ISO"), idata->getISOSpeed(),
Glib::ustring::format (std::setw (3), std::fixed, std::setprecision (2), idata->getFocalLen()));
expcomp = Glib::ustring (idata->expcompToString (idata->getExpComp(), true)); // maskZeroexpcomp
if (expcomp != "") {
infoString2 = Glib::ustring::compose ("%1 <span size=\"large\">%2</span><span size=\"small\">EV</span>",
infoString2,
expcomp /*Glib::ustring(idata->expcompToString(idata->getExpComp()))*/);
}
infoString3 = Glib::ustring::compose ("<span size=\"small\">%1</span><span>%2</span>",
escapeHtmlChars (Glib::path_get_dirname (openThm->getFileName())) + G_DIR_SEPARATOR_S,
escapeHtmlChars (Glib::path_get_basename (openThm->getFileName())) );
int ww = ipc->getFullWidth();
int hh = ipc->getFullHeight();
//megapixels
infoString4 = Glib::ustring::compose ("<span size=\"small\">%1 MP (%2x%3)</span>", Glib::ustring::format (std::setw (4), std::fixed, std::setprecision (1), (float)ww * hh / 1000000), ww, hh);
infoString = Glib::ustring::compose ("%1\n%2\n%3\n%4", infoString1, infoString2, infoString3, infoString4);
} else {
infoString = M ("QINFO_NOEXIF");
}
iareapanel->imageArea->setInfoText (infoString);
iareapanel->imageArea->infoEnabled (info->get_active ());
}
void EditorPanel::hideHistoryActivated ()
{
removeIfThere (hpanedl, leftbox, false);
if (hidehp->get_active()) {
hpanedl->pack1 (*leftbox, false, false);
}
options.showHistory = hidehp->get_active();
if (options.showHistory) {
hidehp->set_image (*iHistoryHide);
} else {
hidehp->set_image (*iHistoryShow);
}
tbShowHideSidePanels_managestate();
}
void EditorPanel::tbRightPanel_1_toggled ()
{
/*
removeIfThere (hpanedr, vboxright, false);
if (tbRightPanel_1->get_active()){
hpanedr->pack2(*vboxright, false, true);
tbRightPanel_1->set_image (*iRightPanel_1_Hide);
}
else {
tbRightPanel_1->set_image (*iRightPanel_1_Show);
}
tbShowHideSidePanels_managestate();
*/
if (vboxright) {
if (tbRightPanel_1->get_active()) {
vboxright->show();
tbRightPanel_1->set_image (*iRightPanel_1_Hide);
} else {
vboxright->hide();
tbRightPanel_1->set_image (*iRightPanel_1_Show);
}
tbShowHideSidePanels_managestate();
}
}
void EditorPanel::tbTopPanel_1_visible (bool visible)
{
if (!tbTopPanel_1) {
return;
}
if (visible) {
tbTopPanel_1->show();
} else {
tbTopPanel_1->hide();
}
}
void EditorPanel::tbTopPanel_1_toggled ()
{
if (catalogPane) { // catalogPane does not exist in multitab mode
if (tbTopPanel_1->get_active()) {
catalogPane->show();
tbTopPanel_1->set_image (*iTopPanel_1_Hide);
options.editorFilmStripOpened = true;
} else {
catalogPane->hide();
tbTopPanel_1->set_image (*iTopPanel_1_Show);
options.editorFilmStripOpened = false;
}
tbShowHideSidePanels_managestate();
}
}
/*
* WARNING: Take care of the simpleEditor value when adding or modifying shortcut keys,
* since handleShortcutKey is now also triggered in simple editor mode
*/
bool EditorPanel::handleShortcutKey (GdkEventKey* event)
{
bool ctrl = event->state & GDK_CONTROL_MASK;
bool shift = event->state & GDK_SHIFT_MASK;
bool alt = event->state & GDK_MOD1_MASK;
#ifdef __WIN32__
bool altgr = event->state & GDK_MOD2_MASK;
#else
bool altgr = event->state & GDK_MOD5_MASK;
#endif
// Editor Layout
switch (event->keyval) {
case GDK_KEY_L:
if (tbTopPanel_1) {
tbTopPanel_1->set_active (!tbTopPanel_1->get_active()); // toggle top panel
}
if (ctrl) {
hidehp->set_active (!hidehp->get_active()); // toggle History (left panel)
}
if (alt) {
tbRightPanel_1->set_active (!tbRightPanel_1->get_active()); // toggle right panel
}
return true;
break;
case GDK_KEY_l:
if (!shift && !alt /*&& !ctrl*/) {
hidehp->set_active (!hidehp->get_active()); // toggle History (left panel)
return true;
}
if (alt && !ctrl) { // toggle right panel
tbRightPanel_1->set_active (!tbRightPanel_1->get_active());
return true;
}
if (alt && ctrl) { // toggle left and right panels
hidehp->set_active (!hidehp->get_active());
tbRightPanel_1->set_active (!tbRightPanel_1->get_active());
return true;
}
break;
case GDK_KEY_m: // Maximize preview panel: hide top AND right AND history panels
if (!ctrl && !alt) {
toggleSidePanels();
return true;
}
break;
case GDK_KEY_M: // Maximize preview panel: hide top AND right AND history panels AND (fit image preview)
if (!ctrl && !alt) {
toggleSidePanelsZoomFit();
return true;
}
break;
}
#ifdef __WIN32__
if (!alt && !ctrl && !altgr && event->hardware_keycode == 0x39 ) {
iareapanel->imageArea->previewModePanel->togglebackColor();
return true;
}
#else
if (!alt && !ctrl && !altgr && event->hardware_keycode == 0x12 ) {
iareapanel->imageArea->previewModePanel->togglebackColor();
return true;
}
#endif
if (!alt) {
if (!ctrl) {
// Normal
switch (event->keyval) {
case GDK_KEY_bracketright:
tpc->coarse->rotateRight();
return true;
case GDK_KEY_bracketleft:
tpc->coarse->rotateLeft();
return true;
case GDK_KEY_i:
case GDK_KEY_I:
info->set_active (!info->get_active());
return true;
case GDK_KEY_B:
beforeAfter->set_active (!beforeAfter->get_active());
return true;
case GDK_KEY_plus:
case GDK_KEY_equal:
case GDK_KEY_KP_Add:
iareapanel->imageArea->zoomPanel->zoomInClicked();
return true;
case GDK_KEY_minus:
case GDK_KEY_underscore:
case GDK_KEY_KP_Subtract:
iareapanel->imageArea->zoomPanel->zoomOutClicked();
return true;
case GDK_KEY_z://GDK_1
iareapanel->imageArea->zoomPanel->zoom11Clicked();
return true;
/*
#ifndef __WIN32__
case GDK_KEY_9: // toggle background color of the preview
iareapanel->imageArea->previewModePanel->togglebackColor();
return true;
#endif
*/
case GDK_KEY_r: //preview mode Red
iareapanel->imageArea->previewModePanel->toggleR();
return true;
case GDK_KEY_g: //preview mode Green
iareapanel->imageArea->previewModePanel->toggleG();
return true;
case GDK_KEY_b: //preview mode Blue
iareapanel->imageArea->previewModePanel->toggleB();
return true;
case GDK_KEY_v: //preview mode Luminosity
iareapanel->imageArea->previewModePanel->toggleL();
return true;
case GDK_KEY_F: //preview mode Focus Mask
iareapanel->imageArea->previewModePanel->toggleFocusMask();
return true;
case GDK_KEY_f:
iareapanel->imageArea->zoomPanel->zoomFitClicked();
return true;
case GDK_KEY_less:
iareapanel->imageArea->indClippedPanel->toggleClipped (true);
return true;
case GDK_KEY_greater:
iareapanel->imageArea->indClippedPanel->toggleClipped (false);
return true;
case GDK_KEY_F5:
openThm->openDefaultViewer ((event->state & GDK_SHIFT_MASK) ? 2 : 1);
return true;
case GDK_KEY_y: // synchronize filebrowser with image in Editor
if (!simpleEditor && fPanel && !fname.empty()) {
fPanel->fileCatalog->selectImage (fname, false);
return true;
}
break; // to avoid gcc complain
case GDK_KEY_x: // clear filters and synchronize filebrowser with image in Editor
if (!simpleEditor && fPanel && !fname.empty()) {
fPanel->fileCatalog->selectImage (fname, true);
return true;
}
break; // to avoid gcc complain
}
} else {
// With control
switch (event->keyval) {
case GDK_KEY_S:
saveProfile();
setProgressStr (M ("PROGRESSBAR_PROCESSING_PROFILESAVED"));
return true;
case GDK_KEY_s:
saveAsPressed();
return true;
case GDK_KEY_b:
if (!simpleEditor) {
queueImgPressed();
}
return true;
case GDK_KEY_e:
sendToGimpPressed();
return true;
case GDK_KEY_z:
history->undo ();
return true;
case GDK_KEY_Z:
history->redo ();
return true;
case GDK_KEY_F5:
openThm->openDefaultViewer (3);
return true;
}
} //if (!ctrl)
} //if (!alt)
if (alt) {
switch (event->keyval) {
case GDK_KEY_s:
history->addBookmarkPressed ();
setProgressStr (M ("PROGRESSBAR_SNAPSHOT_ADDED"));
return true;
case GDK_KEY_f:
iareapanel->imageArea->zoomPanel->zoomFitCropClicked();
return true;
}
}
if (shift) {
switch (event->keyval) {
case GDK_KEY_F3: // open Previous image from Editor's perspective
if (!simpleEditor && fPanel && !fname.empty()) {
EditorPanel::openPreviousEditorImage();
return true;
}
break; // to avoid gcc complain
case GDK_KEY_F4: // open next image from Editor's perspective
if (!simpleEditor && fPanel && !fname.empty()) {
EditorPanel::openNextEditorImage();
return true;
}
break; // to avoid gcc complain
}
}
if (tpc->getToolBar() && tpc->getToolBar()->handleShortcutKey (event)) {
return true;
}
if (tpc->handleShortcutKey (event)) {
return true;
}
if (!simpleEditor && fPanel) {
if (fPanel->handleShortcutKey (event)) {
return true;
}
}
return false;
}
void EditorPanel::procParamsChanged (Thumbnail* thm, int whoChangedIt)
{
if (whoChangedIt != EDITOR) {
PartialProfile pp (true);
pp.set (true);
* (pp.pparams) = openThm->getProcParams();
tpc->profileChange (&pp, rtengine::EvProfileChangeNotification, M ("PROGRESSDLG_PROFILECHANGEDINBROWSER"));
pp.deleteInstance();
}
}
bool EditorPanel::idle_saveImage (ProgressConnector<rtengine::IImage16*> *pc, Glib::ustring fname, SaveFormat sf)
{
rtengine::IImage16* img = pc->returnValue();
delete pc;
if ( img ) {
setProgressStr (M ("GENERAL_SAVE"));
setProgress (0.9f);
ProgressConnector<int> *ld = new ProgressConnector<int>();
img->setSaveProgressListener (parent->getProgressListener());
if (sf.format == "tif")
ld->startFunc (sigc::bind (sigc::mem_fun (img, &rtengine::IImage16::saveAsTIFF), fname, sf.tiffBits, sf.tiffUncompressed),
sigc::bind (sigc::mem_fun (*this, &EditorPanel::idle_imageSaved), ld, img, fname, sf));
else if (sf.format == "png")
ld->startFunc (sigc::bind (sigc::mem_fun (img, &rtengine::IImage16::saveAsPNG), fname, sf.pngCompression, sf.pngBits),
sigc::bind (sigc::mem_fun (*this, &EditorPanel::idle_imageSaved), ld, img, fname, sf));
else if (sf.format == "jpg")
ld->startFunc (sigc::bind (sigc::mem_fun (img, &rtengine::IImage16::saveAsJPEG), fname, sf.jpegQuality, sf.jpegSubSamp),
sigc::bind (sigc::mem_fun (*this, &EditorPanel::idle_imageSaved), ld, img, fname, sf));
else
delete ld;
} else {
Glib::ustring msg_ = Glib::ustring ("<b>") + fname + ": Error during image processing\n</b>";
Gtk::MessageDialog msgd (*parent, msg_, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
msgd.run ();
saveimgas->set_sensitive (true);
sendtogimp->set_sensitive (true);
isProcessing = false;
}
rtengine::ImageSource* imgsrc = isrc->getImageSource ();
imgsrc->setProgressListener (this);
return false;
}
bool EditorPanel::idle_imageSaved (ProgressConnector<int> *pc, rtengine::IImage16* img, Glib::ustring fname, SaveFormat sf)
{
img->free ();
if (! pc->returnValue() ) {
openThm->imageDeveloped ();
// save processing parameters, if needed
if (sf.saveParams) {
rtengine::procparams::ProcParams pparams;
ipc->getParams (&pparams);
// We keep the extension to avoid overwriting the profile when we have
// the same output filename with different extension
//pparams.save (removeExtension (fname) + ".out" + paramFileExtension);
pparams.save (fname + ".out" + paramFileExtension);
}
} else {
error (M ("MAIN_MSG_CANNOTSAVE"), fname);
}
saveimgas->set_sensitive (true);
sendtogimp->set_sensitive (true);
parent->setProgressStr ("");
parent->setProgress (0.);
setProgressState (false);
delete pc;
SoundManager::playSoundAsync (options.sndBatchQueueDone);
isProcessing = false;
return false;
}
BatchQueueEntry* EditorPanel::createBatchQueueEntry ()
{
rtengine::procparams::ProcParams pparams;
ipc->getParams (&pparams);
//rtengine::ProcessingJob* job = rtengine::ProcessingJob::create (ipc->getInitialImage(), pparams);
rtengine::ProcessingJob* job = rtengine::ProcessingJob::create (openThm->getFileName (), openThm->getType() == FT_Raw, pparams);
int fullW = 0, fullH = 0;
isrc->getImageSource()->getFullSize (fullW, fullH, pparams.coarse.rotate == 90 || pparams.coarse.rotate == 270 ? TR_R90 : TR_NONE);
int prevh = BatchQueue::calcMaxThumbnailHeight();
int prevw = int ((size_t)fullW * (size_t)prevh / (size_t)fullH);
return new BatchQueueEntry (job, pparams, openThm->getFileName(), prevw, prevh, openThm);
}
void EditorPanel::saveAsPressed ()
{
if (!ipc || !openThm) {
return;
}
bool fnameOK = false;
Glib::ustring fnameOut;
SaveAsDialog* saveAsDialog;
auto toplevel = static_cast<Gtk::Window*> (get_toplevel ());
if (Glib::file_test (options.lastSaveAsPath, Glib::FILE_TEST_IS_DIR)) {
saveAsDialog = new SaveAsDialog (options.lastSaveAsPath, toplevel);
} else {
saveAsDialog = new SaveAsDialog (PlacesBrowser::userPicturesDir (), toplevel);
}
saveAsDialog->set_default_size (options.saveAsDialogWidth, options.saveAsDialogHeight);
saveAsDialog->setInitialFileName (lastSaveAsFileName);
saveAsDialog->setImagePath (fname);
do {
int result = saveAsDialog->run ();
// The SaveAsDialog ensure that a filename has been specified
fnameOut = saveAsDialog->getFileName ();
options.lastSaveAsPath = saveAsDialog->getDirectory ();
saveAsDialog->get_size(options.saveAsDialogWidth, options.saveAsDialogHeight);
options.autoSuffix = saveAsDialog->getAutoSuffix ();
options.saveMethodNum = saveAsDialog->getSaveMethodNum ();
lastSaveAsFileName = Glib::path_get_basename (removeExtension (fnameOut));
SaveFormat sf = saveAsDialog->getFormat ();
options.saveFormat = sf;
options.forceFormatOpts = saveAsDialog->getForceFormatOpts ();
if (result != Gtk::RESPONSE_OK) {
break;
}
if (saveAsDialog->getImmediately ()) {
// separate filename and the path to the destination directory
Glib::ustring dstdir = Glib::path_get_dirname (fnameOut);
Glib::ustring dstfname = Glib::path_get_basename (removeExtension (fnameOut));
Glib::ustring dstext = getExtension (fnameOut);
if (saveAsDialog->getAutoSuffix()) {
Glib::ustring fnameTemp;
for (int tries = 0; tries < 100; tries++) {
if (tries == 0) {
fnameTemp = Glib::ustring::compose ("%1.%2", Glib::build_filename (dstdir, dstfname), dstext);
} else {
fnameTemp = Glib::ustring::compose ("%1-%2.%3", Glib::build_filename (dstdir, dstfname), tries, dstext);
}
if (!Glib::file_test (fnameTemp, Glib::FILE_TEST_EXISTS)) {
fnameOut = fnameTemp;
fnameOK = true;
break;
}
}
}
// check if it exists
if (!fnameOK) {
fnameOK = confirmOverwrite (*saveAsDialog, fnameOut);
}
if (fnameOK) {
isProcessing = true;
// save image
rtengine::procparams::ProcParams pparams;
ipc->getParams (&pparams);
rtengine::ProcessingJob* job = rtengine::ProcessingJob::create (ipc->getInitialImage(), pparams);
ProgressConnector<rtengine::IImage16*> *ld = new ProgressConnector<rtengine::IImage16*>();
ld->startFunc (sigc::bind (sigc::ptr_fun (&rtengine::processImage), job, err, parent->getProgressListener(), options.tunnelMetaData, false ),
sigc::bind (sigc::mem_fun ( *this, &EditorPanel::idle_saveImage ), ld, fnameOut, sf ));
saveimgas->set_sensitive (false);
sendtogimp->set_sensitive (false);
}
} else {
BatchQueueEntry* bqe = createBatchQueueEntry ();
bqe->outFileName = fnameOut;
bqe->saveFormat = saveAsDialog->getFormat ();
bqe->forceFormatOpts = saveAsDialog->getForceFormatOpts ();
parent->addBatchQueueJob (bqe, saveAsDialog->getToHeadOfQueue ());
fnameOK = true;
}
// ask parent to redraw file browser
// ... or does it automatically when the tab is switched to it
} while (!fnameOK);
saveAsDialog->hide();
delete saveAsDialog;
}
void EditorPanel::queueImgPressed ()
{
if (!ipc || !openThm) {
return;
}
saveProfile ();
parent->addBatchQueueJob (createBatchQueueEntry ());
}
void EditorPanel::sendToGimpPressed ()
{
if (!ipc || !openThm) {
return;
}
// develop image
rtengine::procparams::ProcParams pparams;
ipc->getParams (&pparams);
rtengine::ProcessingJob* job = rtengine::ProcessingJob::create (ipc->getInitialImage(), pparams);
ProgressConnector<rtengine::IImage16*> *ld = new ProgressConnector<rtengine::IImage16*>();
ld->startFunc (sigc::bind (sigc::ptr_fun (&rtengine::processImage), job, err, parent->getProgressListener(), options.tunnelMetaData, false ),
sigc::bind (sigc::mem_fun ( *this, &EditorPanel::idle_sendToGimp ), ld, openThm->getFileName() ));
saveimgas->set_sensitive (false);
sendtogimp->set_sensitive (false);
}
void EditorPanel::openPreviousEditorImage()
{
if (!simpleEditor && fPanel && !fname.empty()) {
fPanel->fileCatalog->openNextPreviousEditorImage (fname, false, NAV_PREVIOUS);
}
}
void EditorPanel::openNextEditorImage()
{
if (!simpleEditor && fPanel && !fname.empty()) {
fPanel->fileCatalog->openNextPreviousEditorImage (fname, false, NAV_NEXT);
}
}
void EditorPanel::syncFileBrowser() // synchronize filebrowser with image in Editor
{
if (!simpleEditor && fPanel && !fname.empty()) {
fPanel->fileCatalog->selectImage (fname, false);
}
}
bool EditorPanel::idle_sendToGimp ( ProgressConnector<rtengine::IImage16*> *pc, Glib::ustring fname)
{
rtengine::IImage16* img = pc->returnValue();
delete pc;
if (img) {
// get file name base
Glib::ustring shortname = removeExtension (Glib::path_get_basename (fname));
Glib::ustring dirname = Glib::get_tmp_dir ();
Glib::ustring fname = Glib::build_filename (dirname, shortname);
SaveFormat sf;
sf.format = "tif";
sf.tiffBits = 16;
sf.tiffUncompressed = true;
sf.saveParams = true;
Glib::ustring fileName = Glib::ustring::compose ("%1.%2", fname, sf.format);
// TODO: Just list all file with a suitable name instead of brute force...
int tries = 1;
while (Glib::file_test (fileName, Glib::FILE_TEST_EXISTS) && tries < 1000) {
fileName = Glib::ustring::compose("%1-%2.%3", fname, tries, sf.format);
tries++;
}
if (tries == 1000) {
img->free ();
return false;
}
ProgressConnector<int> *ld = new ProgressConnector<int>();
img->setSaveProgressListener (parent->getProgressListener());
ld->startFunc (sigc::bind (sigc::mem_fun (img, &rtengine::IImage16::saveAsTIFF), fileName, sf.tiffBits, sf.tiffUncompressed),
sigc::bind (sigc::mem_fun (*this, &EditorPanel::idle_sentToGimp), ld, img, fileName));
} else {
Glib::ustring msg_ = Glib::ustring ("<b> Error during image processing\n</b>");
Gtk::MessageDialog msgd (*parent, msg_, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
msgd.run ();
saveimgas->set_sensitive (true);
sendtogimp->set_sensitive (true);
}
return false;
}
bool EditorPanel::idle_sentToGimp (ProgressConnector<int> *pc, rtengine::IImage16* img, Glib::ustring filename)
{
img->free ();
int errore = pc->returnValue();
delete pc;
if (!errore) {
saveimgas->set_sensitive (true);
sendtogimp->set_sensitive (true);
parent->setProgressStr ("");
parent->setProgress (0.);
bool success = false;
if (options.editorToSendTo == 1) {
success = ExtProgStore::openInGimp (filename);
} else if (options.editorToSendTo == 2) {
success = ExtProgStore::openInPhotoshop (filename);
} else if (options.editorToSendTo == 3) {
success = ExtProgStore::openInCustomEditor (filename);
}
if (!success) {
Gtk::MessageDialog msgd (*parent, M("MAIN_MSG_CANNOTSTARTEDITOR"), false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
msgd.set_secondary_text (M("MAIN_MSG_CANNOTSTARTEDITOR_SECONDARY"));
msgd.set_title (M("MAIN_BUTTON_SENDTOEDITOR"));
msgd.run ();
}
}
return false;
}
void EditorPanel::historyBeforeLineChanged (const rtengine::procparams::ProcParams& params)
{
if (beforeIpc) {
ProcParams* pparams = beforeIpc->beginUpdateParams ();
*pparams = params;
beforeIpc->endUpdateParams (rtengine::EvProfileChanged); // starts the IPC processing
}
}
void EditorPanel::beforeAfterToggled ()
{
if (!ipc) {
return;
}
removeIfThere (beforeAfterBox, beforeBox, false);
removeIfThere (afterBox, afterHeaderBox, false);
if (beforeIarea) {
if (beforeIpc) {
beforeIpc->stopProcessing ();
}
iareapanel->setBeforeAfterViews (nullptr, iareapanel);
iareapanel->imageArea->iLinkedImageArea = nullptr;
delete beforeIarea;
beforeIarea = nullptr;
if (beforeIpc) {
beforeIpc->setPreviewImageListener (nullptr);
}
delete beforePreviewHandler;
beforePreviewHandler = nullptr;
if (beforeIpc) {
rtengine::StagedImageProcessor::destroy (beforeIpc);
}
beforeIpc = nullptr;
}
if (beforeAfter->get_active ()) {
int errorCode = 0;
rtengine::InitialImage *beforeImg = rtengine::InitialImage::load ( isrc->getImageSource ()->getFileName(), openThm->getType() == FT_Raw , &errorCode, nullptr);
if ( !beforeImg || errorCode ) {
return;
}
beforeIarea = new ImageAreaPanel ();
int HeaderBoxHeight = 17;
beforeLabel = Gtk::manage (new Gtk::Label ());
beforeLabel->set_markup (Glib::ustring ("<b>") + M ("GENERAL_BEFORE") + "</b>");
tbBeforeLock = Gtk::manage (new Gtk::ToggleButton ());
tbBeforeLock->set_tooltip_markup (M ("MAIN_TOOLTIP_BEFOREAFTERLOCK"));
tbBeforeLock->signal_toggled().connect ( sigc::mem_fun (*this, &EditorPanel::tbBeforeLock_toggled) );
beforeHeaderBox = Gtk::manage (new Gtk::HBox ());
beforeHeaderBox->pack_end (*tbBeforeLock, Gtk::PACK_SHRINK, 2);
beforeHeaderBox->pack_end (*beforeLabel, Gtk::PACK_SHRINK, 2);
beforeHeaderBox->set_size_request (0, HeaderBoxHeight);
history->blistenerLock ? tbBeforeLock->set_image (*iBeforeLockON) : tbBeforeLock->set_image (*iBeforeLockOFF);
tbBeforeLock->set_active (history->blistenerLock);
beforeBox = Gtk::manage (new Gtk::VBox ());
beforeBox->pack_start (*beforeHeaderBox, Gtk::PACK_SHRINK, 2);
beforeBox->pack_start (*beforeIarea);
afterLabel = Gtk::manage (new Gtk::Label ());
afterLabel->set_markup (Glib::ustring ("<b>") + M ("GENERAL_AFTER") + "</b>");
afterHeaderBox = Gtk::manage (new Gtk::HBox ());
afterHeaderBox->set_size_request (0, HeaderBoxHeight);
afterHeaderBox->pack_end (*afterLabel, Gtk::PACK_SHRINK, 2);
afterBox->pack_start (*afterHeaderBox, Gtk::PACK_SHRINK, 2);
afterBox->reorder_child (*afterHeaderBox, 0);
beforeAfterBox->pack_start (*beforeBox);
beforeAfterBox->reorder_child (*beforeBox, 0);
beforeAfterBox->show_all ();
beforePreviewHandler = new PreviewHandler ();
beforeIpc = rtengine::StagedImageProcessor::create (beforeImg);
beforeIpc->setPreviewScale (10);
beforeIpc->setPreviewImageListener (beforePreviewHandler);
beforeIarea->imageArea->setPreviewHandler (beforePreviewHandler);
beforeIarea->imageArea->setImProcCoordinator (beforeIpc);
beforeIarea->imageArea->setPreviewModePanel (iareapanel->imageArea->previewModePanel);
beforeIarea->imageArea->setIndicateClippedPanel (iareapanel->imageArea->indClippedPanel);
iareapanel->imageArea->iLinkedImageArea = beforeIarea->imageArea;
iareapanel->setBeforeAfterViews (beforeIarea, iareapanel);
beforeIarea->setBeforeAfterViews (beforeIarea, iareapanel);
rtengine::procparams::ProcParams params;
if (history->getBeforeLineParams (params)) {
historyBeforeLineChanged (params);
}
}
}
void EditorPanel::tbBeforeLock_toggled ()
{
history->blistenerLock = tbBeforeLock->get_active();
tbBeforeLock->get_active() ? tbBeforeLock->set_image (*iBeforeLockON) : tbBeforeLock->set_image (*iBeforeLockOFF);
}
void EditorPanel::histogramChanged (LUTu & histRed, LUTu & histGreen, LUTu & histBlue, LUTu & histLuma, LUTu & histToneCurve, LUTu & histLCurve, LUTu & histCCurve, /*LUTu & histCLurve, LUTu & histLLCurve,*/ LUTu & histLCAM, LUTu & histCCAM,
LUTu & histRedRaw, LUTu & histGreenRaw, LUTu & histBlueRaw , LUTu & histChroma, LUTu & histLRETI)
{
if (histogramPanel) {
histogramPanel->histogramChanged (histRed, histGreen, histBlue, histLuma, histRedRaw, histGreenRaw, histBlueRaw, histChroma);
}
tpc->updateCurveBackgroundHistogram (histToneCurve, histLCurve, histCCurve,/*histCLurve, histLLCurve,*/ histLCAM, histCCAM, histRed, histGreen, histBlue, histLuma, histLRETI);
}
bool EditorPanel::CheckSidePanelsVisibility()
{
if (tbTopPanel_1) {
return tbTopPanel_1->get_active() || tbRightPanel_1->get_active() || hidehp->get_active();
}
return tbRightPanel_1->get_active() || hidehp->get_active();
}
void EditorPanel::toggleSidePanels()
{
// Maximize preview panel:
// toggle top AND right AND history panels
bool bAllSidePanelsVisible;
bAllSidePanelsVisible = CheckSidePanelsVisibility();
if (tbTopPanel_1) {
tbTopPanel_1->set_active (!bAllSidePanelsVisible);
}
tbRightPanel_1->set_active (!bAllSidePanelsVisible);
hidehp->set_active (!bAllSidePanelsVisible);
if (!bAllSidePanelsVisible) {
tbShowHideSidePanels->set_image (*iShowHideSidePanels);
} else {
tbShowHideSidePanels->set_image (*iShowHideSidePanels_exit);
}
}
void EditorPanel::toggleSidePanelsZoomFit()
{
toggleSidePanels();
// fit image preview
// !!! TODO this does not want to work... seems to have an effect on a subsequent key press
// iarea->imageArea->zoomPanel->zoomFitClicked();
}
void EditorPanel::tbShowHideSidePanels_managestate()
{
bool bAllSidePanelsVisible;
bAllSidePanelsVisible = CheckSidePanelsVisibility();
ShowHideSidePanelsconn.block (true);
tbShowHideSidePanels->set_active (!bAllSidePanelsVisible);
ShowHideSidePanelsconn.block (false);
}
void EditorPanel::updateProfiles(const Glib::ustring &printerProfile, rtengine::RenderingIntent printerIntent, bool printerBPC)
{
colorMgmtToolBar->canSoftProof(!printerProfile.empty() && printerProfile != "None");
}
void EditorPanel::updateTPVScrollbar (bool hide)
{
tpc->updateTPVScrollbar (hide);
}
void EditorPanel::updateTabsUsesIcons (bool useIcons)
{
tpc->updateTabsUsesIcons (useIcons);
}
void EditorPanel::updateHistogramPosition (int oldPosition, int newPosition)
{
switch (newPosition) {
case 0:
// No histogram
if (!oldPosition) {
// An histogram actually exist, we delete it
delete histogramPanel;
histogramPanel = nullptr;
}
// else no need to create it
break;
case 1:
// Histogram on the left pane
if (oldPosition == 0) {
// There was no Histogram before, so we create it
histogramPanel = Gtk::manage (new HistogramPanel ());
leftbox->pack_start (*histogramPanel, Gtk::PACK_SHRINK, 2);
} else if (oldPosition == 2) {
// The histogram was on the right side, so we move it to the left
histogramPanel->reference();
removeIfThere (vboxright, histogramPanel, false);
leftbox->pack_start (*histogramPanel, Gtk::PACK_SHRINK, 2);
histogramPanel->unreference();
}
histogramPanel->reorder (Gtk::POS_LEFT);
leftbox->reorder_child (*histogramPanel, 0);
break;
case 2:
default:
// Histogram on the right pane
if (oldPosition == 0) {
// There was no Histogram before, so we create it
histogramPanel = Gtk::manage (new HistogramPanel ());
vboxright->pack_start (*histogramPanel, Gtk::PACK_SHRINK, 2);
} else if (oldPosition == 1) {
// The histogram was on the left side, so we move it to the right
histogramPanel->reference();
removeIfThere (leftbox, histogramPanel, false);
vboxright->pack_start (*histogramPanel, Gtk::PACK_SHRINK, 2);
histogramPanel->unreference();
}
histogramPanel->reorder (Gtk::POS_RIGHT);
vboxright->reorder_child (*histogramPanel, 0);
break;
}
iareapanel->imageArea->setPointerMotionHListener (histogramPanel);
}
void EditorPanel::defaultMonitorProfileChanged(const Glib::ustring &profile_name, bool auto_monitor_profile)
{
colorMgmtToolBar->defaultMonitorProfileChanged(profile_name, auto_monitor_profile);
}