Move the external command helper into the external program store singleton.
This commit is contained in:
@@ -80,40 +80,6 @@ std::string safe_locale_from_utf8 (const Glib::ustring& utf8_str)
|
|||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool safe_spawn_command_line_async (const Glib::ustring& cmd_utf8)
|
|
||||||
{
|
|
||||||
std::string cmd;
|
|
||||||
bool success = false;
|
|
||||||
|
|
||||||
try {
|
|
||||||
cmd = Glib::filename_from_utf8(cmd_utf8);
|
|
||||||
printf ("command line: %s\n", cmd.c_str());
|
|
||||||
Glib::spawn_command_line_async (cmd.c_str());
|
|
||||||
success = true;
|
|
||||||
} catch (Glib::Exception& ex) {
|
|
||||||
printf ("%s\n", ex.what().c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool safe_spawn_command_line_sync (const Glib::ustring& cmd_utf8)
|
|
||||||
{
|
|
||||||
int exitStatus = -1;
|
|
||||||
|
|
||||||
try {
|
|
||||||
//cmd = Glib::filename_from_utf8(cmd_utf8);
|
|
||||||
printf ("command line: %s\n", cmd_utf8.c_str());
|
|
||||||
|
|
||||||
// if it crashes here on windows, make sure you have the GTK runtime files gspawn-win32-helper*.exe files in RT directory
|
|
||||||
Glib::spawn_command_line_sync (cmd_utf8, NULL, NULL, &exitStatus);
|
|
||||||
} catch (Glib::Exception& ex) {
|
|
||||||
printf ("%s\n", ex.what().c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
return (exitStatus == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Opens a file for binary writing and request exclusive lock (cases were you need "wb" mode plus locking)
|
// Opens a file for binary writing and request exclusive lock (cases were you need "wb" mode plus locking)
|
||||||
// (Important on Windows to prevent Explorer to crash RT when parallel scanning e.g. a currently written image file)
|
// (Important on Windows to prevent Explorer to crash RT when parallel scanning e.g. a currently written image file)
|
||||||
FILE * safe_g_fopen_WriteBinLock(const Glib::ustring& fname)
|
FILE * safe_g_fopen_WriteBinLock(const Glib::ustring& fname)
|
||||||
|
@@ -5,9 +5,6 @@
|
|||||||
#include <glibmm.h>
|
#include <glibmm.h>
|
||||||
#include <giomm.h>
|
#include <giomm.h>
|
||||||
|
|
||||||
bool safe_spawn_command_line_async (const Glib::ustring& cmd_utf8);
|
|
||||||
bool safe_spawn_command_line_sync (const Glib::ustring& cmd_utf8);
|
|
||||||
|
|
||||||
Glib::ustring safe_filename_to_utf8 (const std::string& src);
|
Glib::ustring safe_filename_to_utf8 (const std::string& src);
|
||||||
Glib::ustring safe_locale_to_utf8 (const std::string& src); // from rtengine
|
Glib::ustring safe_locale_to_utf8 (const std::string& src); // from rtengine
|
||||||
std::string safe_locale_from_utf8 (const Glib::ustring& utf8_str);
|
std::string safe_locale_from_utf8 (const Glib::ustring& utf8_str);
|
||||||
|
@@ -1740,99 +1740,21 @@ bool EditorPanel::idle_sentToGimp(ProgressConnector<int> *pc, rtengine::IImage16
|
|||||||
parent->setProgressStr("");
|
parent->setProgressStr("");
|
||||||
parent->setProgress(0.);
|
parent->setProgress(0.);
|
||||||
bool success = false;
|
bool success = false;
|
||||||
Glib::ustring cmdLine;
|
|
||||||
Glib::ustring executable;
|
|
||||||
|
|
||||||
// start gimp
|
|
||||||
if (options.editorToSendTo == 1) {
|
if (options.editorToSendTo == 1) {
|
||||||
#ifdef WIN32
|
success = ExtProgStore::openInGimp (filename);
|
||||||
executable = Glib::build_filename (Glib::build_filename(options.gimpDir, "bin"), "gimp-win-remote");
|
|
||||||
cmdLine = Glib::ustring("\"") + executable + Glib::ustring("\" gimp-2.4.exe ") + Glib::ustring("\"") + filename + Glib::ustring("\"");
|
|
||||||
|
|
||||||
if ( safe_file_test(executable, (Glib::FILE_TEST_EXISTS | Glib::FILE_TEST_IS_EXECUTABLE)) ) {
|
|
||||||
success = safe_spawn_command_line_async (cmdLine);
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined __APPLE__
|
|
||||||
cmdLine = Glib::ustring("open -a /Applications/GIMP.app \'") + filename + Glib::ustring("\'");
|
|
||||||
success = safe_spawn_command_line_async (cmdLine);
|
|
||||||
std::cout << cmdLine << std::endl;
|
|
||||||
#else
|
|
||||||
cmdLine = Glib::ustring("gimp \"") + filename + Glib::ustring("\"");
|
|
||||||
success = safe_spawn_command_line_async (cmdLine);
|
|
||||||
std::cout << cmdLine << std::endl;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!success) {
|
|
||||||
#ifdef WIN32
|
|
||||||
int ver = 12;
|
|
||||||
|
|
||||||
while (!success && ver) {
|
|
||||||
executable = Glib::build_filename (Glib::build_filename(options.gimpDir, "bin"), Glib::ustring::compose(Glib::ustring("gimp-2.%1.exe"), ver));
|
|
||||||
|
|
||||||
if ( safe_file_test(executable, (Glib::FILE_TEST_EXISTS | Glib::FILE_TEST_IS_EXECUTABLE)) ) {
|
|
||||||
cmdLine = Glib::ustring("\"") + executable + Glib::ustring("\" \"") + filename + Glib::ustring("\"");
|
|
||||||
success = safe_spawn_command_line_async (cmdLine);
|
|
||||||
}
|
|
||||||
|
|
||||||
ver--;
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined __APPLE__
|
|
||||||
cmdLine = Glib::ustring("open -a /Applications/Gimp.app/Contents/Resources/start \'") + filename + Glib::ustring("\'");
|
|
||||||
success = safe_spawn_command_line_async (cmdLine);
|
|
||||||
std::cout << cmdLine << std::endl;
|
|
||||||
#else
|
|
||||||
cmdLine = Glib::ustring("gimp-remote \"") + filename + Glib::ustring("\"");
|
|
||||||
success = safe_spawn_command_line_async (cmdLine);
|
|
||||||
std::cout << cmdLine << std::endl;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
} else if (options.editorToSendTo == 2) {
|
} else if (options.editorToSendTo == 2) {
|
||||||
#ifdef WIN32
|
success = ExtProgStore::openInPhotoshop (filename);
|
||||||
executable = Glib::build_filename(options.psDir, "Photoshop.exe");
|
|
||||||
|
|
||||||
if ( safe_file_test(executable, (Glib::FILE_TEST_EXISTS | Glib::FILE_TEST_IS_EXECUTABLE)) ) {
|
|
||||||
cmdLine = Glib::ustring("\"") + executable + Glib::ustring("\" \"") + filename + Glib::ustring("\"");
|
|
||||||
success = safe_spawn_command_line_async (cmdLine);
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
#ifdef __APPLE__
|
|
||||||
cmdLine = Glib::ustring("open -a \'") + Glib::build_filename(options.psDir, "Photoshop.app\' ") + Glib::ustring("\'") + filename + Glib::ustring("\'");
|
|
||||||
#else
|
|
||||||
cmdLine = Glib::ustring("\"") + Glib::build_filename(options.psDir, "Photoshop.exe") + Glib::ustring("\" \"") + filename + Glib::ustring("\"");
|
|
||||||
#endif
|
|
||||||
success = safe_spawn_command_line_async (cmdLine);
|
|
||||||
std::cout << cmdLine << std::endl;
|
|
||||||
#endif
|
|
||||||
} else if (options.editorToSendTo == 3) {
|
} else if (options.editorToSendTo == 3) {
|
||||||
#ifdef WIN32
|
success = ExtProgStore::openInCustomEditor (filename);
|
||||||
|
|
||||||
if ( safe_file_test(options.customEditorProg, (Glib::FILE_TEST_EXISTS | Glib::FILE_TEST_IS_EXECUTABLE)) ) {
|
|
||||||
cmdLine = Glib::ustring("\"") + options.customEditorProg + Glib::ustring("\" \"") + filename + Glib::ustring("\"");
|
|
||||||
success = safe_spawn_command_line_async (cmdLine);
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
#ifdef __APPLE__
|
|
||||||
cmdLine = options.customEditorProg + Glib::ustring(" \"") + filename + Glib::ustring("\"");
|
|
||||||
#else
|
|
||||||
cmdLine = Glib::ustring("\"") + options.customEditorProg + Glib::ustring("\" \"") + filename + Glib::ustring("\"");
|
|
||||||
#endif
|
|
||||||
success = safe_spawn_command_line_async (cmdLine);
|
|
||||||
std::cout << cmdLine << std::endl;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
Gtk::MessageDialog* msgd = new Gtk::MessageDialog (*parent, M("MAIN_MSG_CANNOTSTARTEDITOR"), false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
|
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_secondary_text (M("MAIN_MSG_CANNOTSTARTEDITOR_SECONDARY"));
|
||||||
msgd->set_title (M("MAIN_BUTTON_SENDTOEDITOR"));
|
msgd.set_title (M("MAIN_BUTTON_SENDTOEDITOR"));
|
||||||
msgd->run ();
|
msgd.run ();
|
||||||
delete msgd;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
311
rtgui/extprog.cc
311
rtgui/extprog.cc
@@ -16,183 +16,316 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
|
* along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
#include "extprog.h"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#include "extprog.h"
|
|
||||||
#include "multilangmgr.h"
|
|
||||||
#include "../rtengine/safegtk.h"
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
// for GCC32
|
|
||||||
#ifndef _WIN32_IE
|
|
||||||
#define _WIN32_IE 0x0600
|
|
||||||
#endif
|
|
||||||
#include <shlobj.h>
|
#include <shlobj.h>
|
||||||
#endif
|
#endif
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
|
#include "options.h"
|
||||||
|
#include "multilangmgr.h"
|
||||||
|
|
||||||
ExtProgAction::ExtProgAction() {}
|
Glib::ustring ExtProgAction::getFullName () const
|
||||||
|
|
||||||
ExtProgAction::ExtProgAction(const ExtProgAction* other, int target)
|
|
||||||
: target(target), filePathEXE(other->filePathEXE), preparams(other->preparams), name(other->name) { }
|
|
||||||
|
|
||||||
Glib::ustring ExtProgAction::GetFullName()
|
|
||||||
{
|
{
|
||||||
return name + " [" + M(Glib::ustring::compose("EXTPROGTARGET_%1", target)) + "]";
|
return name + " [" + M(Glib::ustring::compose("EXTPROGTARGET_%1", target)) + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExtProgAction::Execute(std::vector<Glib::ustring> fileNames)
|
bool ExtProgAction::execute (const std::vector<Glib::ustring>& fileNames) const
|
||||||
{
|
{
|
||||||
if (fileNames.empty()) {
|
if (fileNames.empty ()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if they all exists (maybe not precessed yet)
|
// Check if they all exists as they may not be processed yet.
|
||||||
for (int i = 0; i < fileNames.size(); i++) {
|
for (const auto& fileName : fileNames) {
|
||||||
if (!safe_file_test(fileNames[i], Glib::FILE_TEST_EXISTS)) {
|
|
||||||
Gtk::MessageDialog msgd (M("MAIN_MSG_IMAGEUNPROCESSED"), true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
|
if (Glib::file_test (fileName, Glib::FILE_TEST_EXISTS)) {
|
||||||
msgd.run ();
|
continue;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Gtk::MessageDialog (M("MAIN_MSG_IMAGEUNPROCESSED"), true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true).run ();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Glib::ustring cmdLine = "\"" + filePathEXE + "\"";
|
Glib::ustring cmdLine = "\"" + filePathEXE + "\"";
|
||||||
|
|
||||||
if (preparams.length() > 0) {
|
if (!preparams.empty()) {
|
||||||
cmdLine += " " + preparams;
|
cmdLine += " " + preparams;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < fileNames.size(); i++) {
|
for (const auto& fileName : fileNames) {
|
||||||
cmdLine += " \"" + fileNames[i] + "\"";
|
cmdLine += " \"" + fileName + "\"";
|
||||||
}
|
}
|
||||||
|
|
||||||
return safe_spawn_command_line_async (cmdLine);
|
return ExtProgStore::spawnCommandAsync (cmdLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Generates as singleton
|
|
||||||
ExtProgStore* ExtProgStore::getInstance()
|
ExtProgStore* ExtProgStore::getInstance()
|
||||||
{
|
{
|
||||||
static ExtProgStore instance_;
|
static ExtProgStore instance_;
|
||||||
return &instance_;
|
return &instance_;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExtProgStore::~ExtProgStore()
|
|
||||||
{
|
|
||||||
for (list<ExtProgAction*>::iterator it = lActions.begin(); it != lActions.end(); it++) {
|
|
||||||
delete *it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reads all profiles from the given profiles dir
|
// Reads all profiles from the given profiles dir
|
||||||
void ExtProgStore::init ()
|
void ExtProgStore::init ()
|
||||||
{
|
{
|
||||||
MyMutex::MyLock lock(mtx);
|
MyMutex::MyLock lock(mtx);
|
||||||
|
|
||||||
lActions.clear();
|
actions.clear ();
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
|
|
||||||
SearchProg("Photoshop", "Adobe\\Adobe Photoshop CS%1 (64 Bit)\\Photoshop.exe", "Adobe\\Adobe Photoshop CS%1\\Photoshop.exe", 9, false, true);
|
// Please do not add obscure little tools here, only widely used programs.
|
||||||
SearchProg("Photomatix Pro", "PhotomatixPro%1\\PhotomatixPro.exe", "", 9, true, true);
|
// They should also have a proper setup program and therefore a standard path.
|
||||||
SearchProg("Paint.NET", "Paint.NET\\PaintDotNet.exe", "", 0, false, true);
|
|
||||||
SearchProg("MS Image Composition Editor", "Microsoft Research\\Image Composite Editor\\ICE.exe", "", 0, false, true);
|
|
||||||
SearchProg("PTGui", "PTGui\\PTGui.exe", "", 0, false, true);
|
|
||||||
SearchProg("GeoSetter", "GeoSetter\\GeoSetter.exe", "", 0, true, true);
|
|
||||||
SearchProg("FastStone Image Viewer", "FastStone Image Viewer\\FSViewer.exe", "", 0, true, true);
|
|
||||||
SearchProg("FastPictureViewer", "FastPictureViewer\\FastPictureViewer.exe", "", 0, true, true);
|
|
||||||
|
|
||||||
if (!SearchProg("Autopano Giga 3", "Kolor\\Autopano Giga 3.%1\\AutopanoGiga_x64.exe", "Kolor\\Autopano Giga 3.%1\\AutopanoGiga.exe", 15, true, true)) {
|
searchProgram ("Photoshop", "Adobe\\Adobe Photoshop CS%1 (64 Bit)\\Photoshop.exe", "Adobe\\Adobe Photoshop CS%1\\Photoshop.exe", 9, false, true);
|
||||||
if ( !SearchProg("Autopano Pro 3", "Kolor\\Autopano Pro 3.%1\\AutopanoPro_x64.exe", "Kolor\\Autopano Pro 3.%1\\AutopanoPro.exe", 15, true, true)) {
|
searchProgram ("Photomatix Pro", "PhotomatixPro%1\\PhotomatixPro.exe", "", 9, true, true);
|
||||||
if (!SearchProg("Autopano Giga 2", "Kolor\\Autopano Giga 2.%1\\AutopanoGiga_x64.exe", "Kolor\\Autopano Giga 2.%1\\AutopanoGiga.exe", 6, true, true)) {
|
searchProgram ("Paint.NET", "Paint.NET\\PaintDotNet.exe", "", 0, false, true);
|
||||||
SearchProg("Autopano Pro 2", "Kolor\\Autopano Pro 2.%1\\AutopanoPro_x64.exe", "Kolor\\Autopano Pro 2.%1\\AutopanoPro.exe", 6, true, true);
|
searchProgram ("MS Image Composition Editor", "Microsoft Research\\Image Composite Editor\\ICE.exe", "", 0, false, true);
|
||||||
|
searchProgram ("PTGui", "PTGui\\PTGui.exe", "", 0, false, true);
|
||||||
|
searchProgram ("GeoSetter", "GeoSetter\\GeoSetter.exe", "", 0, true, true);
|
||||||
|
searchProgram ("FastStone Image Viewer", "FastStone Image Viewer\\FSViewer.exe", "", 0, true, true);
|
||||||
|
searchProgram ("FastPictureViewer", "FastPictureViewer\\FastPictureViewer.exe", "", 0, true, true);
|
||||||
|
|
||||||
|
if (!searchProgram ("Autopano Giga 3", "Kolor\\Autopano Giga 3.%1\\AutopanoGiga_x64.exe", "Kolor\\Autopano Giga 3.%1\\AutopanoGiga.exe", 15, true, true)) {
|
||||||
|
if (!searchProgram ("Autopano Pro 3", "Kolor\\Autopano Pro 3.%1\\AutopanoPro_x64.exe", "Kolor\\Autopano Pro 3.%1\\AutopanoPro.exe", 15, true, true)) {
|
||||||
|
if (!searchProgram ("Autopano Giga 2", "Kolor\\Autopano Giga 2.%1\\AutopanoGiga_x64.exe", "Kolor\\Autopano Giga 2.%1\\AutopanoGiga.exe", 6, true, true)) {
|
||||||
|
searchProgram ("Autopano Pro 2", "Kolor\\Autopano Pro 2.%1\\AutopanoPro_x64.exe", "Kolor\\Autopano Pro 2.%1\\AutopanoPro.exe", 6, true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DO NOT add obscure little tools here, only widely used programs with proper setup program to have a standard path
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExtProgStore::SearchProg(Glib::ustring name, Glib::ustring exePath, Glib::ustring exePath86, int maxVer, bool allowRaw, bool allowQueueProcess)
|
bool ExtProgStore::searchProgram (const Glib::ustring& name,
|
||||||
|
const Glib::ustring& exePath,
|
||||||
|
const Glib::ustring& exePath86,
|
||||||
|
int maxVer,
|
||||||
|
bool allowRaw,
|
||||||
|
bool allowQueueProcess)
|
||||||
{
|
{
|
||||||
bool found = false;
|
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
// get_user_special_dir crashes on some Windows configurations.
|
// get_user_special_dir crashes on some Windows configurations.
|
||||||
// so we use the safe native functions here
|
|
||||||
static Glib::ustring progFilesDir, progFilesDirx86;
|
static Glib::ustring progFilesDir, progFilesDirx86;
|
||||||
|
|
||||||
if (progFilesDir.empty()) {
|
if (progFilesDir.empty ()) {
|
||||||
WCHAR pathW[MAX_PATH] = {0};
|
WCHAR pathW[MAX_PATH];
|
||||||
char pathA[MAX_PATH];
|
char pathA[MAX_PATH];
|
||||||
|
|
||||||
// First prio folder (64bit, otherwise 32bit)
|
if (SHGetSpecialFolderPathW (NULL, pathW, CSIDL_PROGRAM_FILES, false)) {
|
||||||
if (SHGetSpecialFolderPathW(NULL, pathW, CSIDL_PROGRAM_FILES, false)) {
|
if (WideCharToMultiByte (CP_UTF8, 0, pathW, -1, pathA, MAX_PATH, 0, 0)) {
|
||||||
char pathA[MAX_PATH];
|
progFilesDir = pathA;
|
||||||
WideCharToMultiByte(CP_UTF8, 0, pathW, -1, pathA, MAX_PATH, 0, 0);
|
}
|
||||||
progFilesDir = Glib::ustring(pathA);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SHGetSpecialFolderPathW(NULL, pathW, CSIDL_PROGRAM_FILESX86, false)) {
|
if (SHGetSpecialFolderPathW (NULL, pathW, CSIDL_PROGRAM_FILESX86, false)) {
|
||||||
WideCharToMultiByte(CP_UTF8, 0, pathW, -1, pathA, MAX_PATH, 0, 0);
|
if (WideCharToMultiByte (CP_UTF8, 0, pathW, -1, pathA, MAX_PATH, 0, 0)) {
|
||||||
progFilesDirx86 = Glib::ustring(pathA);
|
progFilesDirx86 = pathA;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exePath86.empty()) {
|
ExtProgAction action;
|
||||||
exePath86 = exePath;
|
action.name = name;
|
||||||
}
|
action.target = (allowRaw ? 1 : 2);
|
||||||
|
|
||||||
ExtProgAction *pAct = new ExtProgAction();
|
auto& filePath = action.filePathEXE;
|
||||||
pAct->name = name;
|
|
||||||
pAct->target = (allowRaw ? 1 : 2);
|
|
||||||
|
|
||||||
if (maxVer > 0) {
|
if (maxVer > 0) {
|
||||||
for (int verNo = maxVer; verNo >= 0; verNo--) {
|
|
||||||
pAct->filePathEXE = progFilesDir + "\\" + Glib::ustring::compose(exePath, verNo);
|
|
||||||
|
|
||||||
if (safe_file_test(pAct->filePathEXE, Glib::FILE_TEST_EXISTS)) {
|
for (auto ver = maxVer; ver >= 0; ver--) {
|
||||||
|
|
||||||
|
filePath = progFilesDir + "\\" + Glib::ustring::compose(exePath, ver);
|
||||||
|
|
||||||
|
if (Glib::file_test (filePath, Glib::FILE_TEST_EXISTS)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
pAct->filePathEXE = progFilesDirx86 + "\\" + Glib::ustring::compose(exePath86, verNo);
|
if (!exePath86.empty ()) {
|
||||||
|
|
||||||
if (safe_file_test(pAct->filePathEXE, Glib::FILE_TEST_EXISTS)) {
|
filePath = progFilesDirx86 + "\\" + Glib::ustring::compose(exePath86, ver);
|
||||||
break;
|
|
||||||
|
if (Glib::file_test (filePath, Glib::FILE_TEST_EXISTS)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pAct->filePathEXE = "";
|
filePath.clear ();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pAct->filePathEXE = progFilesDir + "\\" + exePath;
|
|
||||||
|
|
||||||
if (!safe_file_test(pAct->filePathEXE, Glib::FILE_TEST_EXISTS)) {
|
do {
|
||||||
|
|
||||||
pAct->filePathEXE = progFilesDirx86 + "\\" + exePath86;
|
filePath = progFilesDir + "\\" + exePath;
|
||||||
|
|
||||||
if (!safe_file_test(pAct->filePathEXE, Glib::FILE_TEST_EXISTS)) {
|
if (Glib::file_test (filePath, Glib::FILE_TEST_EXISTS)) {
|
||||||
pAct->filePathEXE = "";
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
if (!exePath86.empty ()) {
|
||||||
|
|
||||||
|
filePath = progFilesDirx86 + "\\" + exePath86;
|
||||||
|
|
||||||
|
if (Glib::file_test (filePath, Glib::FILE_TEST_EXISTS)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
filePath.clear ();
|
||||||
|
|
||||||
|
} while (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pAct->filePathEXE.length() > 0) {
|
if (!action.filePathEXE.empty ()) {
|
||||||
lActions.push_back(pAct);
|
|
||||||
|
actions.push_back (action);
|
||||||
|
|
||||||
// Copy for second target
|
|
||||||
if (allowRaw && allowQueueProcess) {
|
if (allowRaw && allowQueueProcess) {
|
||||||
lActions.push_back(new ExtProgAction(pAct, 2));
|
|
||||||
|
action.target = 2;
|
||||||
|
actions.push_back (action);
|
||||||
}
|
}
|
||||||
|
|
||||||
found = true;
|
return true;
|
||||||
} else {
|
|
||||||
delete pAct;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return found;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ExtProgStore::spawnCommandAsync (const Glib::ustring& cmd)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
|
||||||
|
const auto encodedCmd = Glib::filename_from_utf8 (cmd);
|
||||||
|
Glib::spawn_command_line_async (encodedCmd.c_str ());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} catch (const Glib::Exception& exception) {
|
||||||
|
|
||||||
|
if (options.rtSettings.verbose) {
|
||||||
|
std::cerr << "Failed to execute \"" << cmd << "\": " << exception.what() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ExtProgStore::spawnCommandSync (const Glib::ustring& cmd)
|
||||||
|
{
|
||||||
|
auto exitStatus = -1;
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
Glib::spawn_command_line_sync (cmd, NULL, NULL, &exitStatus);
|
||||||
|
|
||||||
|
} catch (const Glib::Exception& exception) {
|
||||||
|
|
||||||
|
if (options.rtSettings.verbose) {
|
||||||
|
std::cerr << "Failed to execute \"" << cmd << "\": " << exception.what() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return exitStatus == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ExtProgStore::openInGimp (const Glib::ustring& fileName)
|
||||||
|
{
|
||||||
|
#if defined WIN32
|
||||||
|
|
||||||
|
auto executable = Glib::build_filename (options.gimpDir, "bin", "gimp-win-remote");
|
||||||
|
auto cmdLine = Glib::ustring::compose ("\"%1\" gimp-2.4.exe \"%2\"", executable, fileName);
|
||||||
|
auto success = spawnCommandAsync (cmdLine);
|
||||||
|
|
||||||
|
#elif defined __APPLE__
|
||||||
|
|
||||||
|
auto cmdLine = Glib::ustring("open -a /Applications/GIMP.app \'") + fileName + Glib::ustring("\'");
|
||||||
|
auto success = spawnCommandAsync (cmdLine);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
auto cmdLine = Glib::ustring("gimp \"") + fileName + Glib::ustring("\"");
|
||||||
|
auto success = spawnCommandAsync (cmdLine);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
|
||||||
|
for (auto ver = 12; ver >= 0; --ver) {
|
||||||
|
|
||||||
|
executable = Glib::build_filename (options.gimpDir, "bin", Glib::ustring::compose (Glib::ustring("gimp-2.%1.exe"), ver));
|
||||||
|
cmdLine = Glib::ustring::compose ("\"%1\" \"%2\"", executable, fileName);
|
||||||
|
success = spawnCommandAsync (cmdLine);
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined __APPLE__
|
||||||
|
|
||||||
|
cmdLine = Glib::ustring("open -a /Applications/Gimp.app/Contents/Resources/start \'") + fileName + Glib::ustring("\'");
|
||||||
|
success = ExtProgStore::spawnCommandAsync (cmdLine);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
cmdLine = Glib::ustring("gimp-remote \"") + fileName + Glib::ustring("\"");
|
||||||
|
success = ExtProgStore::spawnCommandAsync (cmdLine);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ExtProgStore::openInPhotoshop (const Glib::ustring& fileName)
|
||||||
|
{
|
||||||
|
#if defined WIN32
|
||||||
|
|
||||||
|
const auto executable = Glib::build_filename(options.psDir, "Photoshop.exe");
|
||||||
|
const auto cmdLine = Glib::ustring("\"") + executable + Glib::ustring("\" \"") + fileName + Glib::ustring("\"");
|
||||||
|
|
||||||
|
#elif defined __APPLE__
|
||||||
|
|
||||||
|
const auto cmdLine = Glib::ustring("open -a \'") + Glib::build_filename(options.psDir, "Photoshop.app\' ") + Glib::ustring("\'") + fileName + Glib::ustring("\'");
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
const auto cmdLine = Glib::ustring("\"") + Glib::build_filename(options.psDir, "Photoshop.exe") + Glib::ustring("\" \"") + fileName + Glib::ustring("\"");
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return spawnCommandAsync (cmdLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ExtProgStore::openInCustomEditor (const Glib::ustring& fileName)
|
||||||
|
{
|
||||||
|
#if defined WIN32
|
||||||
|
|
||||||
|
const auto cmdLine = Glib::ustring("\"") + options.customEditorProg + Glib::ustring("\" \"") + fileName + Glib::ustring("\"");
|
||||||
|
|
||||||
|
#elif defined __APPLE__
|
||||||
|
|
||||||
|
const auto cmdLine = options.customEditorProg + Glib::ustring(" \"") + fileName + Glib::ustring("\"");
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
const auto cmdLine = Glib::ustring("\"") + options.customEditorProg + Glib::ustring("\" \"") + fileName + Glib::ustring("\"");
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return spawnCommandAsync (cmdLine);
|
||||||
}
|
}
|
||||||
|
@@ -20,42 +20,58 @@
|
|||||||
#ifndef _EXTPROG_
|
#ifndef _EXTPROG_
|
||||||
#define _EXTPROG_
|
#define _EXTPROG_
|
||||||
|
|
||||||
#include <glibmm.h>
|
#include <glibmm/ustring.h>
|
||||||
#include <list>
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "threadutils.h"
|
#include "threadutils.h"
|
||||||
|
|
||||||
class ExtProgAction
|
struct ExtProgAction
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
ExtProgAction();
|
|
||||||
ExtProgAction(const ExtProgAction* other, int target);
|
|
||||||
|
|
||||||
Glib::ustring filePathEXE;
|
Glib::ustring filePathEXE;
|
||||||
Glib::ustring preparams; // after EXE and before file names
|
Glib::ustring preparams; // after EXE and before file names
|
||||||
Glib::ustring name; // already localized if necessary
|
Glib::ustring name; // already localized if necessary
|
||||||
int target; // 1=RAW files, 2=batch converted files
|
int target; // 1=RAW files, 2=batch converted files
|
||||||
|
|
||||||
Glib::ustring GetFullName(); // e.g. "Photoshop (RAW)"
|
Glib::ustring getFullName () const; // e.g. "Photoshop (RAW)"
|
||||||
|
|
||||||
virtual bool Execute(std::vector<Glib::ustring> fileNames);
|
bool execute (const std::vector<Glib::ustring>& fileNames) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Stores all external programs that could be called by the user
|
// Stores all external programs that could be called by the user
|
||||||
class ExtProgStore
|
class ExtProgStore
|
||||||
{
|
{
|
||||||
MyMutex mtx; // covers actions
|
MyMutex mtx; // covers actions
|
||||||
|
std::vector<ExtProgAction> actions;
|
||||||
|
|
||||||
bool SearchProg(Glib::ustring name, Glib::ustring exePath, Glib::ustring exePath86, int maxVer, bool allowRaw, bool allowQueueProcess);
|
bool searchProgram (const Glib::ustring& name,
|
||||||
|
const Glib::ustring& exePath,
|
||||||
|
const Glib::ustring& exePath86,
|
||||||
|
int maxVer,
|
||||||
|
bool allowRaw,
|
||||||
|
bool allowQueueProcess);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
~ExtProgStore();
|
|
||||||
|
|
||||||
void init(); // searches computer for installed standard programs
|
|
||||||
static ExtProgStore* getInstance();
|
static ExtProgStore* getInstance();
|
||||||
|
|
||||||
std::list<ExtProgAction*> lActions;
|
// searches computer for installed standard programs
|
||||||
|
void init();
|
||||||
|
|
||||||
|
const std::vector<ExtProgAction>& getActions () const;
|
||||||
|
|
||||||
|
static bool spawnCommandAsync (const Glib::ustring& cmd);
|
||||||
|
static bool spawnCommandSync (const Glib::ustring& cmd);
|
||||||
|
|
||||||
|
static bool openInGimp (const Glib::ustring& fileName);
|
||||||
|
static bool openInPhotoshop (const Glib::ustring& fileName);
|
||||||
|
static bool openInCustomEditor (const Glib::ustring& fileName);
|
||||||
};
|
};
|
||||||
|
|
||||||
#define extProgStore ExtProgStore::getInstance()
|
#define extProgStore ExtProgStore::getInstance()
|
||||||
|
|
||||||
|
inline const std::vector<ExtProgAction>& ExtProgStore::getActions () const
|
||||||
|
{
|
||||||
|
return actions;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -232,11 +232,9 @@ FileBrowser::FileBrowser ()
|
|||||||
mMenuExtProgs.clear();
|
mMenuExtProgs.clear();
|
||||||
amiExtProg = NULL;
|
amiExtProg = NULL;
|
||||||
|
|
||||||
for (std::list<ExtProgAction*>::iterator it = extProgStore->lActions.begin(); it != extProgStore->lActions.end(); it++) {
|
for (const auto& action : extProgStore->getActions ()) {
|
||||||
ExtProgAction* pAct = *it;
|
if (action.target == 1 || action.target == 2) {
|
||||||
|
mMenuExtProgs[action.getFullName ()] = &action;
|
||||||
if (pAct->target == 1 || pAct->target == 2) {
|
|
||||||
mMenuExtProgs[pAct->GetFullName()] = pAct;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,7 +253,7 @@ FileBrowser::FileBrowser ()
|
|||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (std::map<Glib::ustring, ExtProgAction*>::iterator it = mMenuExtProgs.begin(); it != mMenuExtProgs.end(); it++, itemNo++) {
|
for (auto it = mMenuExtProgs.begin(); it != mMenuExtProgs.end(); it++, itemNo++) {
|
||||||
submenuExtProg->attach (*Gtk::manage(amiExtProg[itemNo] = new Gtk::MenuItem ((*it).first)), 0, 1, p, p + 1);
|
submenuExtProg->attach (*Gtk::manage(amiExtProg[itemNo] = new Gtk::MenuItem ((*it).first)), 0, 1, p, p + 1);
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
@@ -268,7 +266,7 @@ FileBrowser::FileBrowser ()
|
|||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (std::map<Glib::ustring, ExtProgAction*>::iterator it = mMenuExtProgs.begin(); it != mMenuExtProgs.end(); it++, itemNo++) {
|
for (auto it = mMenuExtProgs.begin(); it != mMenuExtProgs.end(); it++, itemNo++) {
|
||||||
pmenu->attach (*Gtk::manage(amiExtProg[itemNo] = new Gtk::MenuItem ((*it).first)), 0, 1, p, p + 1);
|
pmenu->attach (*Gtk::manage(amiExtProg[itemNo] = new Gtk::MenuItem ((*it).first)), 0, 1, p, p + 1);
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
@@ -752,7 +750,7 @@ void FileBrowser::menuItemActivated (Gtk::MenuItem* m)
|
|||||||
|
|
||||||
for (int j = 0; j < mMenuExtProgs.size(); j++) {
|
for (int j = 0; j < mMenuExtProgs.size(); j++) {
|
||||||
if (m == amiExtProg[j]) {
|
if (m == amiExtProg[j]) {
|
||||||
ExtProgAction* pAct = mMenuExtProgs[m->get_label()];
|
const auto pAct = mMenuExtProgs[m->get_label()];
|
||||||
|
|
||||||
// Build vector of all file names
|
// Build vector of all file names
|
||||||
std::vector<Glib::ustring> selFileNames;
|
std::vector<Glib::ustring> selFileNames;
|
||||||
@@ -768,7 +766,7 @@ void FileBrowser::menuItemActivated (Gtk::MenuItem* m)
|
|||||||
selFileNames.push_back(fn);
|
selFileNames.push_back(fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
pAct->Execute(selFileNames);
|
pAct->execute (selFileNames);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -93,7 +93,7 @@ protected:
|
|||||||
Gtk::MenuItem* menuExtProg;
|
Gtk::MenuItem* menuExtProg;
|
||||||
Gtk::MenuItem** amiExtProg;
|
Gtk::MenuItem** amiExtProg;
|
||||||
Gtk::MenuItem* miOpenDefaultViewer;
|
Gtk::MenuItem* miOpenDefaultViewer;
|
||||||
std::map<Glib::ustring, ExtProgAction*> mMenuExtProgs; // key is menuitem label
|
std::map<Glib::ustring, const ExtProgAction*> mMenuExtProgs; // key is menuitem label
|
||||||
|
|
||||||
Gtk::MenuItem* menuDF;
|
Gtk::MenuItem* menuDF;
|
||||||
Gtk::MenuItem* selectDF;
|
Gtk::MenuItem* selectDF;
|
||||||
|
@@ -29,6 +29,7 @@
|
|||||||
#include "guiutils.h"
|
#include "guiutils.h"
|
||||||
#include "profilestore.h"
|
#include "profilestore.h"
|
||||||
#include "batchqueue.h"
|
#include "batchqueue.h"
|
||||||
|
#include "extprog.h"
|
||||||
#include "../rtengine/safegtk.h"
|
#include "../rtengine/safegtk.h"
|
||||||
|
|
||||||
using namespace rtengine::procparams;
|
using namespace rtengine::procparams;
|
||||||
@@ -254,7 +255,7 @@ rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool retu
|
|||||||
printf("Custom profile builder's command line: %s\n", Glib::ustring(cmdLine).c_str());
|
printf("Custom profile builder's command line: %s\n", Glib::ustring(cmdLine).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool success = safe_spawn_command_line_sync (cmdLine);
|
bool success = ExtProgStore::spawnCommandSync (cmdLine);
|
||||||
|
|
||||||
// Now they SHOULD be there (and potentially "partial"), so try to load them and store it as a full procparam
|
// Now they SHOULD be there (and potentially "partial"), so try to load them and store it as a full procparam
|
||||||
if (success) {
|
if (success) {
|
||||||
|
Reference in New Issue
Block a user