Merge with "Beep6581/dev"
This commit is contained in:
@@ -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)
|
||||
{
|
||||
|
Reference in New Issue
Block a user