Merge with "Beep6581/dev"

This commit is contained in:
Pandagrapher
2023-03-11 11:02:29 +01:00
252 changed files with 9021 additions and 3231 deletions

View File

@@ -39,11 +39,14 @@
#include "procparamchangers.h"
#include "placesbrowser.h"
#include "pathutils.h"
#include "rtappchooserdialog.h"
#include "thumbnail.h"
#include "toolpanelcoord.h"
#ifdef WIN32
#include "windows.h"
#include "../rtengine/winutils.h"
#endif
using namespace rtengine::procparams;
@@ -134,6 +137,235 @@ bool find_default_monitor_profile (GdkWindow *rootwin, Glib::ustring &defprof, G
}
#endif
bool hasUserOnlyPermission(const Glib::ustring &dirname)
{
#if defined(__linux__) || defined(__APPLE__)
const Glib::RefPtr<Gio::File> file = Gio::File::create_for_path(dirname);
const Glib::RefPtr<Gio::FileInfo> file_info = file->query_info("owner::user,unix::mode");
if (!file_info) {
return false;
}
const Glib::ustring owner = file_info->get_attribute_string("owner::user");
const guint32 mode = file_info->get_attribute_uint32("unix::mode");
return (mode & 0777) == 0700 && owner == Glib::get_user_name();
#elif defined(WIN32)
const Glib::RefPtr<Gio::File> file = Gio::File::create_for_path(dirname);
const Glib::RefPtr<Gio::FileInfo> file_info = file->query_info("owner::user");
if (!file_info) {
return false;
}
// Current user must be the owner.
const Glib::ustring user_name = Glib::get_user_name();
const Glib::ustring owner = file_info->get_attribute_string("owner::user");
if (user_name != owner) {
return false;
}
// Get security descriptor and discretionary access control list.
PACL dacl = nullptr;
PSECURITY_DESCRIPTOR sec_desc_raw_ptr = nullptr;
auto win_error = GetNamedSecurityInfo(
dirname.c_str(),
SE_FILE_OBJECT,
DACL_SECURITY_INFORMATION,
nullptr,
nullptr,
&dacl,
nullptr,
&sec_desc_raw_ptr
);
const WinLocalPtr<PSECURITY_DESCRIPTOR> sec_desc_ptr(sec_desc_raw_ptr);
if (win_error != ERROR_SUCCESS) {
return false;
}
// Must not inherit permissions.
SECURITY_DESCRIPTOR_CONTROL sec_desc_control;
DWORD revision;
if (!(
GetSecurityDescriptorControl(sec_desc_ptr, &sec_desc_control, &revision)
&& sec_desc_control & SE_DACL_PROTECTED
)) {
return false;
}
// Check that there is one entry allowing full access.
ULONG acl_entry_count;
PEXPLICIT_ACCESS acl_entry_list_raw = nullptr;
win_error = GetExplicitEntriesFromAcl(dacl, &acl_entry_count, &acl_entry_list_raw);
const WinLocalPtr<PEXPLICIT_ACCESS> acl_entry_list(acl_entry_list_raw);
if (win_error != ERROR_SUCCESS || acl_entry_count != 1) {
return false;
}
const EXPLICIT_ACCESS &ace = acl_entry_list[0];
if (
ace.grfAccessMode != GRANT_ACCESS
|| (ace.grfAccessPermissions & FILE_ALL_ACCESS) != FILE_ALL_ACCESS
|| ace.Trustee.TrusteeForm != TRUSTEE_IS_SID // Should already be SID, but double check.
) {
return false;
}
// ACE must be for the current user.
HANDLE process_token_raw;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &process_token_raw)) {
return false;
}
const WinHandle process_token(process_token_raw);
DWORD actual_token_info_size = 0;
GetTokenInformation(process_token, TokenUser, nullptr, 0, &actual_token_info_size);
if (!actual_token_info_size) {
return false;
}
const WinHeapPtr<PTOKEN_USER> user_token_ptr(actual_token_info_size);
if (!user_token_ptr || !GetTokenInformation(
process_token,
TokenUser,
user_token_ptr,
actual_token_info_size,
&actual_token_info_size
)) {
return false;
}
return EqualSid(ace.Trustee.ptstrName, user_token_ptr->User.Sid);
#endif
return false;
}
/**
* Sets read and write permissions, and optionally the execute permission, for
* the user and no permissions for others.
*/
void setUserOnlyPermission(const Glib::RefPtr<Gio::File> file, bool execute)
{
#if defined(__linux__) || defined(__APPLE__)
const Glib::RefPtr<Gio::FileInfo> file_info = file->query_info("unix::mode");
if (!file_info) {
return;
}
guint32 mode = file_info->get_attribute_uint32("unix::mode");
mode = (mode & ~0777) | (execute ? 0700 : 0600);
try {
file->set_attribute_uint32("unix::mode", mode, Gio::FILE_QUERY_INFO_NONE);
} catch (Gio::Error &) {
}
#elif defined(WIN32)
// Get the current user's SID.
HANDLE process_token_raw;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &process_token_raw)) {
return;
}
const WinHandle process_token(process_token_raw);
DWORD actual_token_info_size = 0;
GetTokenInformation(process_token, TokenUser, nullptr, 0, &actual_token_info_size);
if (!actual_token_info_size) {
return;
}
const WinHeapPtr<PTOKEN_USER> user_token_ptr(actual_token_info_size);
if (!user_token_ptr || !GetTokenInformation(
process_token,
TokenUser,
user_token_ptr,
actual_token_info_size,
&actual_token_info_size
)) {
return;
}
const PSID user_sid = user_token_ptr->User.Sid;
// Get a handle to the file.
const Glib::ustring filename = file->get_path();
const HANDLE file_handle_raw = CreateFile(
filename.c_str(),
READ_CONTROL | WRITE_DAC,
0,
nullptr,
OPEN_EXISTING,
execute ? FILE_FLAG_BACKUP_SEMANTICS : FILE_ATTRIBUTE_NORMAL,
nullptr
);
if (file_handle_raw == INVALID_HANDLE_VALUE) {
return;
}
const WinHandle file_handle(file_handle_raw);
// Create the user-only permission and set it.
EXPLICIT_ACCESS ea = {
.grfAccessPermissions = FILE_ALL_ACCESS,
.grfAccessMode = GRANT_ACCESS,
.grfInheritance = NO_INHERITANCE,
};
BuildTrusteeWithSid(&(ea.Trustee), user_sid);
PACL new_dacl_raw = nullptr;
auto win_error = SetEntriesInAcl(1, &ea, nullptr, &new_dacl_raw);
if (win_error != ERROR_SUCCESS) {
return;
}
const WinLocalPtr<PACL> new_dacl(new_dacl_raw);
SetSecurityInfo(
file_handle,
SE_FILE_OBJECT,
DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
nullptr,
nullptr,
new_dacl,
nullptr
);
#endif
}
/**
* Gets the path to the temp directory, creating it if necessary.
*/
Glib::ustring getTmpDirectory()
{
#if defined(__linux__) || defined(__APPLE__) || defined(WIN32)
static Glib::ustring recent_dir = "";
const Glib::ustring tmp_dir_root = Glib::get_tmp_dir();
const Glib::ustring subdir_base =
Glib::ustring::compose("rawtherapee-%1", Glib::get_user_name());
Glib::ustring dir = Glib::build_filename(tmp_dir_root, subdir_base);
// Returns true if the directory doesn't exist or has the right permissions.
auto is_usable_dir = [](const Glib::ustring &dir_path) {
return !Glib::file_test(dir_path, Glib::FILE_TEST_EXISTS) || (Glib::file_test(dir_path, Glib::FILE_TEST_IS_DIR) && hasUserOnlyPermission(dir_path));
};
if (!(is_usable_dir(dir) || recent_dir.empty())) {
// Try to reuse the random suffix directory.
dir = recent_dir;
}
if (!is_usable_dir(dir)) {
// Create new directory with random suffix.
gchar *const rand_dir = g_dir_make_tmp((subdir_base + "-XXXXXX").c_str(), nullptr);
if (!rand_dir) {
return tmp_dir_root;
}
dir = recent_dir = rand_dir;
g_free(rand_dir);
Glib::RefPtr<Gio::File> file = Gio::File::create_for_path(dir);
setUserOnlyPermission(file, true);
} else if (!Glib::file_test(dir, Glib::FILE_TEST_EXISTS)) {
// Create the directory.
Glib::RefPtr<Gio::File> file = Gio::File::create_for_path(dir);
bool dir_created = file->make_directory();
if (!dir_created) {
return tmp_dir_root;
}
setUserOnlyPermission(file, true);
}
return dir;
#else
return Glib::get_tmp_dir();
#endif
}
}
class EditorPanel::ColorManagementToolbar
@@ -470,7 +702,9 @@ public:
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),
iBeforeLockON (nullptr), iBeforeLockOFF (nullptr),
externalEditorChangedSignal (nullptr),
previewHandler (nullptr), beforePreviewHandler (nullptr),
beforeIarea (nullptr), beforeBox (nullptr), afterBox (nullptr), beforeLabel (nullptr), afterLabel (nullptr),
beforeHeaderBox (nullptr), afterHeaderBox (nullptr), parent (nullptr), parentWindow (nullptr), openThm (nullptr),
selectedFrame(0), isrc (nullptr), ipc (nullptr), beforeIpc (nullptr), err (0), isProcessing (false),
@@ -668,12 +902,14 @@ EditorPanel::EditorPanel (FilePanel* filePanel)
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 ("palette-brush", Gtk::ICON_SIZE_LARGE_TOOLBAR));
sendtogimp = Gtk::manage (new Gtk::Button ());
sendtogimp->set_relief(Gtk::RELIEF_NONE);
sendtogimp->add (*sendToEditorButtonImage);
sendtogimp->set_tooltip_markup (M ("MAIN_BUTTON_SENDTOEDITOR_TOOLTIP"));
setExpandAlignProperties (sendtogimp, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_FILL);
send_to_external = Gtk::manage(new PopUpButton("", false));
send_to_external->set_tooltip_text(M("MAIN_BUTTON_SENDTOEDITOR_TOOLTIP"));
setExpandAlignProperties(send_to_external->buttonGroup, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_FILL);
updateExternalEditorWidget(
options.externalEditorIndex >= 0 ? options.externalEditorIndex : options.externalEditors.size(),
options.externalEditors
);
send_to_external->show();
// Status box
progressLabel = Gtk::manage (new MyProgressBar (300));
@@ -738,7 +974,7 @@ EditorPanel::EditorPanel (FilePanel* filePanel)
iops->attach_next_to (*vsep1, Gtk::POS_LEFT, 1, 1);
if (!gimpPlugin) {
iops->attach_next_to (*sendtogimp, Gtk::POS_LEFT, 1, 1);
iops->attach_next_to(*send_to_external->buttonGroup, Gtk::POS_LEFT, 1, 1);
}
if (!gimpPlugin && !simpleEditor) {
@@ -842,7 +1078,8 @@ EditorPanel::EditorPanel (FilePanel* filePanel)
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) );
send_to_external->signal_changed().connect(sigc::mem_fun(*this, &EditorPanel::sendToExternalChanged));
send_to_external->signal_pressed().connect(sigc::mem_fun(*this, &EditorPanel::sendToExternalPressed));
toggleHistogramProfile->signal_toggled().connect( sigc::mem_fun (*this, &EditorPanel::histogramProfile_toggled) );
if (navPrev) {
@@ -1675,7 +1912,7 @@ bool EditorPanel::handleShortcutKey (GdkEventKey* event)
case GDK_KEY_e:
if (!gimpPlugin) {
sendToGimpPressed();
sendToExternalPressed();
}
return true;
@@ -1776,7 +2013,7 @@ bool EditorPanel::idle_saveImage (ProgressConnector<rtengine::IImagefloat*> *pc,
img->setSaveProgressListener (parent->getProgressListener());
if (sf.format == "tif")
ld->startFunc (sigc::bind (sigc::mem_fun (img, &rtengine::IImagefloat::saveAsTIFF), fname, sf.tiffBits, sf.tiffFloat, sf.tiffUncompressed),
ld->startFunc (sigc::bind (sigc::mem_fun (img, &rtengine::IImagefloat::saveAsTIFF), fname, sf.tiffBits, sf.tiffFloat, sf.tiffUncompressed, sf.bigTiff),
sigc::bind (sigc::mem_fun (*this, &EditorPanel::idle_imageSaved), ld, img, fname, sf, pparams));
else if (sf.format == "png")
ld->startFunc (sigc::bind (sigc::mem_fun (img, &rtengine::IImagefloat::saveAsPNG), fname, sf.pngBits),
@@ -1793,7 +2030,7 @@ bool EditorPanel::idle_saveImage (ProgressConnector<rtengine::IImagefloat*> *pc,
msgd.run ();
saveimgas->set_sensitive (true);
sendtogimp->set_sensitive (true);
send_to_external->set_sensitive(true);
isProcessing = false;
}
@@ -1821,7 +2058,7 @@ bool EditorPanel::idle_imageSaved (ProgressConnector<int> *pc, rtengine::IImagef
}
saveimgas->set_sensitive (true);
sendtogimp->set_sensitive (true);
send_to_external->set_sensitive(true);
parent->setProgressStr ("");
parent->setProgress (0.);
@@ -1932,7 +2169,7 @@ void EditorPanel::saveAsPressed ()
ld->startFunc (sigc::bind (sigc::ptr_fun (&rtengine::processImage), job, err, parent->getProgressListener(), false ),
sigc::bind (sigc::mem_fun ( *this, &EditorPanel::idle_saveImage ), ld, fnameOut, sf, pparams));
saveimgas->set_sensitive (false);
sendtogimp->set_sensitive (false);
send_to_external->set_sensitive(false);
}
} else {
BatchQueueEntry* bqe = createBatchQueueEntry ();
@@ -1963,7 +2200,7 @@ void EditorPanel::queueImgPressed ()
parent->addBatchQueueJob (createBatchQueueEntry ());
}
void EditorPanel::sendToGimpPressed ()
void EditorPanel::sendToExternal()
{
if (!ipc || !openThm) {
return;
@@ -1975,12 +2212,46 @@ void EditorPanel::sendToGimpPressed ()
if (options.editor_bypass_output_profile) {
pparams.icm.outputProfile = rtengine::procparams::ColorManagementParams::NoProfileString;
}
if (!cached_exported_filename.empty() && cached_exported_image == ipc->getInitialImage() && pparams == cached_exported_pparams && Glib::file_test(cached_exported_filename, Glib::FILE_TEST_IS_REGULAR)) {
idle_sentToGimp(nullptr, nullptr, cached_exported_filename);
return;
}
cached_exported_image = ipc->getInitialImage();
cached_exported_pparams = pparams;
cached_exported_filename.clear();
rtengine::ProcessingJob* job = rtengine::ProcessingJob::create (ipc->getInitialImage(), pparams);
ProgressConnector<rtengine::IImagefloat*> *ld = new ProgressConnector<rtengine::IImagefloat*>();
ld->startFunc (sigc::bind (sigc::ptr_fun (&rtengine::processImage), job, err, parent->getProgressListener(), false ),
sigc::bind (sigc::mem_fun ( *this, &EditorPanel::idle_sendToGimp ), ld, openThm->getFileName() ));
saveimgas->set_sensitive (false);
sendtogimp->set_sensitive (false);
send_to_external->set_sensitive(false);
}
void EditorPanel::sendToExternalChanged(int)
{
int index = send_to_external->getSelected();
if (index >= 0 && static_cast<unsigned>(index) == options.externalEditors.size()) {
index = -1;
}
options.externalEditorIndex = index;
if (externalEditorChangedSignal) {
externalEditorChangedSignal->emit();
}
}
void EditorPanel::sendToExternalPressed()
{
if (options.externalEditorIndex == -1) {
// "Other" external editor. Show app chooser dialog to let user pick.
RTAppChooserDialog *dialog = getAppChooserDialog();
dialog->show();
} else {
struct ExternalEditor editor = options.externalEditors.at(options.externalEditorIndex);
external_editor_info = Gio::AppInfo::create_from_commandline(editor.command, editor.name, Gio::APP_INFO_CREATE_NONE);
sendToExternal();
}
}
@@ -1999,7 +2270,7 @@ bool EditorPanel::saveImmediately (const Glib::ustring &filename, const SaveForm
if (gimpPlugin) {
err = img->saveAsTIFF (filename, 32, true, true);
} else if (sf.format == "tif") {
err = img->saveAsTIFF (filename, sf.tiffBits, sf.tiffFloat, sf.tiffUncompressed);
err = img->saveAsTIFF (filename, sf.tiffBits, sf.tiffFloat, sf.tiffUncompressed, sf.bigTiff);
} else if (sf.format == "png") {
err = img->saveAsPNG (filename, sf.pngBits);
} else if (sf.format == "jpg") {
@@ -2034,6 +2305,23 @@ void EditorPanel::syncFileBrowser() // synchronize filebrowser with image in E
}
}
ExternalEditorChangedSignal * EditorPanel::getExternalEditorChangedSignal()
{
return externalEditorChangedSignal;
}
void EditorPanel::setExternalEditorChangedSignal(ExternalEditorChangedSignal *signal)
{
if (externalEditorChangedSignal) {
externalEditorChangedSignalConnection.disconnect();
}
externalEditorChangedSignal = signal;
if (signal) {
externalEditorChangedSignalConnection = signal->connect(
sigc::mem_fun(*this, &EditorPanel::updateExternalEditorSelection));
}
}
void EditorPanel::histogramProfile_toggled()
{
options.rtSettings.HistogramWorking = toggleHistogramProfile->get_active();
@@ -2058,7 +2346,7 @@ bool EditorPanel::idle_sendToGimp ( ProgressConnector<rtengine::IImagefloat*> *p
dirname = options.editor_custom_out_dir;
break;
default: // Options::EDITOR_OUT_DIR_TEMP
dirname = Glib::get_tmp_dir();
dirname = getTmpDirectory();
break;
}
Glib::ustring fullFileName = Glib::build_filename(dirname, shortname);
@@ -2092,14 +2380,14 @@ bool EditorPanel::idle_sendToGimp ( ProgressConnector<rtengine::IImagefloat*> *p
ProgressConnector<int> *ld = new ProgressConnector<int>();
img->setSaveProgressListener (parent->getProgressListener());
ld->startFunc (sigc::bind (sigc::mem_fun (img, &rtengine::IImagefloat::saveAsTIFF), fileName, sf.tiffBits, sf.tiffFloat, sf.tiffUncompressed),
ld->startFunc (sigc::bind (sigc::mem_fun (img, &rtengine::IImagefloat::saveAsTIFF), fileName, sf.tiffBits, sf.tiffFloat, sf.tiffUncompressed, sf.bigTiff),
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);
send_to_external->set_sensitive(true);
}
return false;
@@ -2107,25 +2395,27 @@ bool EditorPanel::idle_sendToGimp ( ProgressConnector<rtengine::IImagefloat*> *p
bool EditorPanel::idle_sentToGimp (ProgressConnector<int> *pc, rtengine::IImagefloat* img, Glib::ustring filename)
{
delete img;
int errore = pc->returnValue();
if (img) {
delete img;
cached_exported_filename = filename;
}
int errore = 0;
setProgressState(false);
delete pc;
if (pc) {
errore = pc->returnValue();
delete pc;
}
if (!errore) {
if ((!img && Glib::file_test(filename, Glib::FILE_TEST_IS_REGULAR)) || (img && !errore)) {
saveimgas->set_sensitive (true);
sendtogimp->set_sensitive (true);
send_to_external->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);
}
setUserOnlyPermission(Gio::File::create_for_path(filename), false);
success = ExtProgStore::openInExternalEditor(filename, external_editor_info);
if (!success) {
Gtk::MessageDialog msgd (*parent, M ("MAIN_MSG_CANNOTSTARTEDITOR"), false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
@@ -2138,6 +2428,48 @@ bool EditorPanel::idle_sentToGimp (ProgressConnector<int> *pc, rtengine::IImagef
return false;
}
RTAppChooserDialog *EditorPanel::getAppChooserDialog()
{
if (!app_chooser_dialog.get()) {
app_chooser_dialog.reset(new RTAppChooserDialog("image/tiff"));
app_chooser_dialog->signal_response().connect(
sigc::mem_fun(*this, &EditorPanel::onAppChooserDialogResponse)
);
app_chooser_dialog->set_modal();
}
return app_chooser_dialog.get();
}
void EditorPanel::onAppChooserDialogResponse(int responseId)
{
switch (responseId) {
case Gtk::RESPONSE_OK:
getAppChooserDialog()->close();
external_editor_info = getAppChooserDialog()->get_app_info();
sendToExternal();
break;
case Gtk::RESPONSE_CANCEL:
case Gtk::RESPONSE_CLOSE:
getAppChooserDialog()->close();
break;
default:
break;
}
}
void EditorPanel::updateExternalEditorSelection()
{
int index = send_to_external->getSelected();
if (index >= 0 && static_cast<unsigned>(index) == options.externalEditors.size()) {
index = -1;
}
if (options.externalEditorIndex != index) {
send_to_external->setSelected(
options.externalEditorIndex >= 0 ? options.externalEditorIndex : options.externalEditors.size());
}
}
void EditorPanel::historyBeforeLineChanged (const rtengine::procparams::ProcParams& params)
{
@@ -2413,6 +2745,45 @@ void EditorPanel::tbShowHideSidePanels_managestate()
ShowHideSidePanelsconn.block (false);
}
void EditorPanel::updateExternalEditorWidget(int selectedIndex, const std::vector<ExternalEditor> &editors)
{
// Remove the editors.
while (send_to_external->getEntryCount()) {
send_to_external->removeEntry(send_to_external->getEntryCount() - 1);
}
// Create new radio button group because they cannot be reused: https://developer-old.gnome.org/gtkmm/3.16/classGtk_1_1RadioButtonGroup.html#details.
send_to_external_radio_group = Gtk::RadioButtonGroup();
// Add the editors.
for (unsigned i = 0; i < editors.size(); i++) {
const auto & name = editors[i].name.empty() ? Glib::ustring(" ") : editors[i].name;
if (!editors[i].icon_serialized.empty()) {
Glib::RefPtr<Gio::Icon> gioIcon;
GError *e = nullptr;
GVariant *icon_variant = g_variant_parse(
nullptr, editors[i].icon_serialized.c_str(), nullptr, nullptr, &e);
if (e) {
std::cerr
<< "Error loading external editor icon from \""
<< editors[i].icon_serialized << "\": " << e->message
<< std::endl;
gioIcon = Glib::RefPtr<Gio::Icon>();
} else {
gioIcon = Gio::Icon::deserialize(Glib::VariantBase(icon_variant));
}
send_to_external->insertEntry(i, gioIcon, name, &send_to_external_radio_group);
} else {
send_to_external->insertEntry(i, "palette-brush", name, &send_to_external_radio_group);
}
}
send_to_external->addEntry("palette-brush", M("GENERAL_OTHER"), &send_to_external_radio_group);
send_to_external->setSelected(selectedIndex);
send_to_external->show();
}
void EditorPanel::updateProfiles (const Glib::ustring &printerProfile, rtengine::RenderingIntent printerIntent, bool printerBPC)
{
}
@@ -2486,6 +2857,13 @@ void EditorPanel::updateHistogramPosition (int oldPosition, int newPosition)
}
void EditorPanel::updateToolPanelToolLocations(
const std::vector<Glib::ustring> &favorites, bool cloneFavoriteTools)
{
if (tpc) {
tpc->updateToolLocations(favorites, cloneFavoriteTools);
}
}
void EditorPanel::defaultMonitorProfileChanged (const Glib::ustring &profile_name, bool auto_monitor_profile)
{