Merge branch 'dev' into metadata-exiv2

This commit is contained in:
Lawrence Lee 2023-04-19 21:14:54 -07:00
commit 1f8e2aaf55
No known key found for this signature in database
GPG Key ID: 048FF2B76A63895F
10 changed files with 124 additions and 45 deletions

View File

@ -1886,8 +1886,9 @@ PREFERENCES_EXTEDITOR_FLOAT32;32-bit float TIFF output
PREFERENCES_EXTERNALEDITOR;External Editor
PREFERENCES_EXTERNALEDITOR_CHANGE;Change Application
PREFERENCES_EXTERNALEDITOR_CHANGE_FILE;Change Executable
PREFERENCES_EXTERNALEDITOR_COLUMN_NAME;Name
PREFERENCES_EXTERNALEDITOR_COLUMN_COMMAND;Command
PREFERENCES_EXTERNALEDITOR_COLUMN_NAME;Name
PREFERENCES_EXTERNALEDITOR_COLUMN_NATIVE_COMMAND;Native command
PREFERENCES_FBROWSEROPTS;File Browser / Thumbnail Options
PREFERENCES_FILEBROWSERTOOLBARSINGLEROW;Compact toolbars in File Browser
PREFERENCES_FLATFIELDFOUND;Found

View File

@ -2257,6 +2257,7 @@ void EditorPanel::sendToExternalPressed()
} 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);
external_editor_native_command = editor.native_command;
sendToExternal();
}
}
@ -2422,7 +2423,7 @@ bool EditorPanel::idle_sentToGimp (ProgressConnector<int> *pc, rtengine::IImagef
setUserOnlyPermission(Gio::File::create_for_path(filename), false);
success = ExtProgStore::openInExternalEditor(filename, external_editor_info);
success = ExtProgStore::openInExternalEditor(filename, external_editor_info, external_editor_native_command);
if (!success) {
Gtk::MessageDialog msgd (*parent, M ("MAIN_MSG_CANNOTSTARTEDITOR"), false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
@ -2454,6 +2455,7 @@ void EditorPanel::onAppChooserDialogResponse(int responseId)
case Gtk::RESPONSE_OK:
getAppChooserDialog()->close();
external_editor_info = getAppChooserDialog()->get_app_info();
external_editor_native_command = false;
sendToExternal();
break;
case Gtk::RESPONSE_CANCEL:

View File

@ -253,6 +253,7 @@ private:
Gtk::Button* navNext;
Gtk::Button* navPrev;
Glib::RefPtr<Gio::AppInfo> external_editor_info;
bool external_editor_native_command;
std::unique_ptr<RTAppChooserDialog> app_chooser_dialog;
ExternalEditorChangedSignal *externalEditorChangedSignal;
sigc::connection externalEditorChangedSignalConnection;

View File

@ -37,6 +37,7 @@ ExternalEditorPreferences::ExternalEditorPreferences():
list_view = Gtk::manage(new Gtk::TreeView());
list_view->set_model(list_model);
list_view->append_column(*Gtk::manage(makeAppColumn()));
list_view->append_column(*Gtk::manage(makeNativeCommandColumn()));
list_view->append_column(*Gtk::manage(makeCommandColumn()));
for (auto &&column : list_view->get_columns()) {
@ -90,19 +91,19 @@ ExternalEditorPreferences::ExternalEditorPreferences():
std::vector<ExternalEditorPreferences::EditorInfo>
ExternalEditorPreferences::getEditors() const
{
std::vector<ExternalEditorPreferences::EditorInfo> editors;
std::vector<EditorInfo> editors;
auto children = list_model->children();
for (auto rowIter = children.begin(); rowIter != children.end(); rowIter++) {
const Gio::Icon *const icon = rowIter->get_value(model_columns.icon).get();
const auto &icon_serialized = icon == nullptr ? "" : icon->serialize().print();
editors.push_back(ExternalEditorPreferences::EditorInfo(
rowIter->get_value(model_columns.name),
rowIter->get_value(model_columns.command),
icon_serialized,
rowIter->get_value(model_columns.other_data)
));
editors.emplace_back(
rowIter->get_value(model_columns.name),
rowIter->get_value(model_columns.command),
icon_serialized,
rowIter->get_value(model_columns.native_command),
rowIter->get_value(model_columns.other_data));
}
return editors;
@ -113,7 +114,7 @@ void ExternalEditorPreferences::setEditors(
{
list_model->clear();
for (const ExternalEditorPreferences::EditorInfo & editor : editors) {
for (const EditorInfo & editor : editors) {
auto row = *list_model->append();
Glib::RefPtr<Gio::Icon> icon;
@ -138,6 +139,7 @@ void ExternalEditorPreferences::setEditors(
row[model_columns.name] = editor.name;
row[model_columns.icon] = icon;
row[model_columns.command] = editor.command;
row[model_columns.native_command] = editor.native_command;
row[model_columns.other_data] = editor.other_data;
}
}
@ -167,8 +169,8 @@ Gtk::TreeViewColumn *ExternalEditorPreferences::makeAppColumn()
col->set_resizable();
col->pack_start(*icon_renderer, false);
col->pack_start(*name_renderer);
col->add_attribute(*icon_renderer, "gicon", model_columns.icon);
col->add_attribute(*name_renderer, "text", model_columns.name);
col->add_attribute(icon_renderer->property_gicon(), model_columns.icon);
col->add_attribute(name_renderer->property_text(), model_columns.name);
col->set_min_width(20);
name_renderer->property_editable() = true;
@ -185,7 +187,7 @@ Gtk::TreeViewColumn *ExternalEditorPreferences::makeCommandColumn()
col->set_title(M("PREFERENCES_EXTERNALEDITOR_COLUMN_COMMAND"));
col->pack_start(*command_renderer);
col->add_attribute(*command_renderer, "text", model_columns.command);
col->add_attribute(command_renderer->property_text(), model_columns.command);
command_renderer->property_editable() = true;
command_renderer->signal_edited().connect(
@ -194,6 +196,24 @@ Gtk::TreeViewColumn *ExternalEditorPreferences::makeCommandColumn()
return col;
}
Gtk::TreeViewColumn *ExternalEditorPreferences::makeNativeCommandColumn()
{
auto toggle_renderer = Gtk::manage(new Gtk::CellRendererToggle());
auto col = Gtk::manage(new Gtk::TreeViewColumn());
col->set_title(M("PREFERENCES_EXTERNALEDITOR_COLUMN_NATIVE_COMMAND"));
col->pack_start(*toggle_renderer);
col->add_attribute(toggle_renderer->property_active(), model_columns.native_command);
toggle_renderer->signal_toggled().connect([this](const Glib::ustring &path) {
const auto row_iter = list_model->get_iter(path);
bool new_value = !row_iter->get_value(model_columns.native_command);
row_iter->set_value(model_columns.native_command, new_value);
});
return col;
}
void ExternalEditorPreferences::onAppChooserDialogResponse(
int response_id, RTAppChooserDialog *dialog)
{
@ -224,6 +244,7 @@ void ExternalEditorPreferences::onFileChooserDialogResponse(
for (const auto &selected : selection) {
auto row = *list_model->get_iter(selected);
row[model_columns.icon] = Glib::RefPtr<Gio::Icon>(nullptr);
row[model_columns.native_command] = false;
row[model_columns.command] =
#ifdef WIN32
'"' + dialog->get_filename() + '"';
@ -313,6 +334,7 @@ void ExternalEditorPreferences::setApp(const Glib::RefPtr<Gio::AppInfo> app_info
row[model_columns.icon] = app_info->get_icon();
row[model_columns.name] = app_info->get_name();
row[model_columns.command] = app_info->get_commandline();
row[model_columns.native_command] = false;
}
}
@ -344,8 +366,16 @@ void ExternalEditorPreferences::updateToolbarSensitivity()
}
ExternalEditorPreferences::EditorInfo::EditorInfo(
Glib::ustring name, Glib::ustring command, Glib::ustring icon_serialized, void *other_data
) : name(name), icon_serialized(icon_serialized), command(command), other_data(other_data)
const Glib::ustring &name,
const Glib::ustring &command,
const Glib::ustring &icon_serialized,
bool native_command,
EditorTag other_data) :
name(name),
icon_serialized(icon_serialized),
command(command),
native_command(native_command),
other_data(other_data)
{
}
@ -354,5 +384,6 @@ ExternalEditorPreferences::ModelColumns::ModelColumns()
add(name);
add(icon);
add(command);
add(native_command);
add(other_data);
}

View File

@ -42,15 +42,22 @@ class FileChooserDialog;
class ExternalEditorPreferences : public Gtk::Box
{
public:
struct EditorTag {
bool selected;
EditorTag(): selected(false) {}
explicit EditorTag(bool selected): selected(selected) {}
};
/**
* Data struct containing information about an external editor.
*/
struct EditorInfo {
explicit EditorInfo(
Glib::ustring name = Glib::ustring(),
Glib::ustring command = Glib::ustring(),
Glib::ustring icon_serialized = Glib::ustring(),
void *other_data = nullptr
const Glib::ustring &name = Glib::ustring(),
const Glib::ustring &command = Glib::ustring(),
const Glib::ustring &icon_serialized = Glib::ustring(),
bool native_command = false,
EditorTag other_data = EditorTag()
);
/**
* Name of the external editor.
@ -65,11 +72,15 @@ public:
* Gio::AppInfo::get_commandline()
*/
Glib::ustring command;
/**
* Use the OS native launcher instead of Gio.
*/
bool native_command;
/**
* Holds any other data associated with the editor. For example, it can
* be used as a tag to uniquely identify the editor.
*/
void *other_data;
EditorTag other_data;
};
ExternalEditorPreferences();
@ -96,7 +107,8 @@ private:
Gtk::TreeModelColumn<Glib::ustring> name;
Gtk::TreeModelColumn<Glib::RefPtr<Gio::Icon>> icon;
Gtk::TreeModelColumn<Glib::ustring> command;
Gtk::TreeModelColumn<void *> other_data;
Gtk::TreeModelColumn<bool> native_command;
Gtk::TreeModelColumn<EditorTag> other_data;
};
ModelColumns model_columns;
@ -124,6 +136,10 @@ private:
* Constructs the column for displaying an editable commandline.
*/
Gtk::TreeViewColumn *makeCommandColumn();
/**
* Constructs the column for displaying the native command toggle.
*/
Gtk::TreeViewColumn *makeNativeCommandColumn();
/**
* Called when the user is done interacting with the app chooser dialog.
* Closes the dialog and updates the selected entry if an app was chosen.

View File

@ -344,8 +344,20 @@ bool ExtProgStore::openInCustomEditor (const Glib::ustring& fileName, const Glib
}
bool ExtProgStore::openInExternalEditor(const Glib::ustring &fileName, const Glib::RefPtr<Gio::AppInfo> &editorInfo)
bool ExtProgStore::openInExternalEditor(const Glib::ustring &fileName, const Glib::RefPtr<Gio::AppInfo> &editorInfo, bool nativeCommand)
{
if (nativeCommand) {
if (rtengine::settings->verbose) {
std::cout << "Launching external editor as native command." << std::endl;
}
const Glib::ustring command = editorInfo->get_commandline();
return openInCustomEditor(fileName, &command);
}
if (rtengine::settings->verbose) {
std::cout << "Launching external editor with Gio." << std::endl;
}
bool success = false;
try {

View File

@ -70,7 +70,7 @@ public:
static bool openInGimp (const Glib::ustring& fileName);
static bool openInPhotoshop (const Glib::ustring& fileName);
static bool openInCustomEditor (const Glib::ustring& fileName, const Glib::ustring* command = nullptr);
static bool openInExternalEditor(const Glib::ustring &fileName, const Glib::RefPtr<Gio::AppInfo> &editorInfo);
static bool openInExternalEditor(const Glib::ustring &fileName, const Glib::RefPtr<Gio::AppInfo> &editorInfo, bool nativeCommand);
};
#define extProgStore ExtProgStore::getInstance()

View File

@ -876,6 +876,7 @@ void Options::readFromFile(Glib::ustring fname)
if (keyFile.has_group("External Editor")) {
if (keyFile.has_key("External Editor", "Names")
|| keyFile.has_key("External Editor", "Commands")
|| keyFile.has_key("External Editor", "NativeCommands")
|| keyFile.has_key("External Editor", "IconsSerialized")) {
// Multiple external editors.
@ -889,6 +890,11 @@ void Options::readFromFile(Glib::ustring fname)
std::vector<Glib::ustring>() :
static_cast<std::vector<Glib::ustring>>(
keyFile.get_string_list("External Editor", "Commands"));
const auto & native_commands =
!keyFile.has_key("External Editor", "NativeCommands") ?
std::vector<bool>() :
static_cast<std::vector<bool>>(
keyFile.get_boolean_list("External Editor", "NativeCommands"));
const auto & icons_serialized =
!keyFile.has_key("External Editor", "IconsSerialized") ?
std::vector<Glib::ustring>() :
@ -902,6 +908,9 @@ void Options::readFromFile(Glib::ustring fname)
for (unsigned i = 0; i < commands.size(); i++) {
externalEditors[i].command = commands[i];
}
for (unsigned i = 0; i < native_commands.size(); i++) {
externalEditors[i].native_command = native_commands[i];
}
for (unsigned i = 0; i < icons_serialized.size(); i++) {
externalEditors[i].icon_serialized = icons_serialized[i];
}
@ -941,7 +950,7 @@ void Options::readFromFile(Glib::ustring fname)
if (editorToSendTo == 1) {
externalEditorIndex = externalEditors.size();
}
externalEditors.push_back(ExternalEditor("GIMP", "\"" + executable + "\"", getIconSerialized(executable)));
externalEditors.emplace_back("GIMP", executable, true, getIconSerialized(executable));
} else {
for (auto ver = 12; ver >= 0; --ver) {
executable = Glib::build_filename(gimpDir, "bin", Glib::ustring::compose(Glib::ustring("gimp-2.%1.exe"), ver));
@ -949,7 +958,7 @@ void Options::readFromFile(Glib::ustring fname)
if (editorToSendTo == 1) {
externalEditorIndex = externalEditors.size();
}
externalEditors.push_back(ExternalEditor("GIMP", "\"" + executable + "\"", getIconSerialized(executable)));
externalEditors.emplace_back("GIMP", executable, true, getIconSerialized(executable));
break;
}
}
@ -964,7 +973,7 @@ void Options::readFromFile(Glib::ustring fname)
if (editorToSendTo == 2) {
externalEditorIndex = externalEditors.size();
}
externalEditors.push_back(ExternalEditor("Photoshop", "\"" + executable + "\"", getIconSerialized(executable)));
externalEditors.emplace_back("Photoshop", executable, true, getIconSerialized(executable));
}
if (keyFile.has_key("External Editor", "CustomEditor")) {
@ -973,20 +982,20 @@ void Options::readFromFile(Glib::ustring fname)
if (editorToSendTo == 3) {
externalEditorIndex = externalEditors.size();
}
externalEditors.push_back(ExternalEditor("-", "\"" + executable + "\"", ""));
externalEditors.emplace_back("-", executable, true, "");
}
}
#elif defined __APPLE__
if (editorToSendTo == 1) {
externalEditorIndex = externalEditors.size();
}
externalEditors.push_back(ExternalEditor("GIMP", "open -a GIMP", "gimp"));
externalEditors.push_back(ExternalEditor("GIMP-dev", "open -a GIMP-dev", "gimp"));
externalEditors.emplace_back("GIMP", "open -a GIMP", true, "");
externalEditors.emplace_back("GIMP-dev", "open -a GIMP-dev", true, "");
if (editorToSendTo == 2) {
externalEditorIndex = externalEditors.size();
}
externalEditors.push_back(ExternalEditor("Photoshop", "open -a Photoshop", ""));
externalEditors.emplace_back("Photoshop", "open -a Photoshop", true, "");
if (keyFile.has_key("External Editor", "CustomEditor")) {
auto executable = keyFile.get_string("External Editor", "CustomEditor");
@ -994,20 +1003,21 @@ void Options::readFromFile(Glib::ustring fname)
if (editorToSendTo == 3) {
externalEditorIndex = externalEditors.size();
}
externalEditors.push_back(ExternalEditor("-", executable, ""));
externalEditors.emplace_back("-", executable, true, "");
}
}
#else
const Glib::ustring gimp_icon_serialized = "('themed', <['gimp', 'gimp-symbolic']>)";
if (Glib::find_program_in_path("gimp").compare("")) {
if (editorToSendTo == 1) {
externalEditorIndex = externalEditors.size();
}
externalEditors.push_back(ExternalEditor("GIMP", "gimp", "gimp"));
externalEditors.emplace_back("GIMP", "gimp", true, gimp_icon_serialized);
} else if (Glib::find_program_in_path("gimp-remote").compare("")) {
if (editorToSendTo == 1) {
externalEditorIndex = externalEditors.size();
}
externalEditors.push_back(ExternalEditor("GIMP", "gimp-remote", "gimp"));
externalEditors.emplace_back("GIMP", "gimp-remote", true, gimp_icon_serialized);
}
if (keyFile.has_key("External Editor", "CustomEditor")) {
@ -1016,7 +1026,7 @@ void Options::readFromFile(Glib::ustring fname)
if (editorToSendTo == 3) {
externalEditorIndex = externalEditors.size();
}
externalEditors.push_back(ExternalEditor("-", executable, ""));
externalEditors.emplace_back("-", executable, true, "");
}
}
#endif
@ -2352,16 +2362,19 @@ void Options::saveToFile(Glib::ustring fname)
{
std::vector<Glib::ustring> names;
std::vector<Glib::ustring> commands;
std::vector<bool> native_commands;
std::vector<Glib::ustring> icons_serialized;
for (const auto & editor : externalEditors) {
names.push_back(editor.name);
commands.push_back(editor.command);
native_commands.push_back(editor.native_command);
icons_serialized.push_back(editor.icon_serialized);
}
keyFile.set_string_list("External Editor", "Names", names);
keyFile.set_string_list("External Editor", "Commands", commands);
keyFile.set_boolean_list("External Editor", "NativeCommands", native_commands);
keyFile.set_string_list("External Editor", "IconsSerialized", icons_serialized);
keyFile.set_integer("External Editor", "EditorIndex", externalEditorIndex);
@ -3052,15 +3065,15 @@ Glib::ustring Options::getICCProfileCopyright()
return Glib::ustring::compose("Copyright RawTherapee %1, CC0", now.get_year());
}
ExternalEditor::ExternalEditor() {}
ExternalEditor::ExternalEditor() = default;
ExternalEditor::ExternalEditor(
const Glib::ustring &name, const Glib::ustring &command, const Glib::ustring &icon_serialized
): name(name), command(command), icon_serialized(icon_serialized) {}
const Glib::ustring &name, const Glib::ustring &command, bool native_command, const Glib::ustring &icon_serialized
): name(name), command(command), native_command(native_command), icon_serialized(icon_serialized) {}
bool ExternalEditor::operator==(const ExternalEditor &other) const
{
return this->name == other.name && this->command == other.command && this->icon_serialized == other.icon_serialized;
return this->name == other.name && this->command == other.command && this->native_command == other.native_command && this->icon_serialized == other.icon_serialized;
}
bool ExternalEditor::operator!=(const ExternalEditor &other) const

View File

@ -54,9 +54,10 @@
struct ExternalEditor {
ExternalEditor();
ExternalEditor(const Glib::ustring &name, const Glib::ustring &command, const Glib::ustring &icon_serialized);
ExternalEditor(const Glib::ustring &name, const Glib::ustring &command, bool native_command, const Glib::ustring &icon_serialized);
Glib::ustring name;
Glib::ustring command;
bool native_command;
Glib::ustring icon_serialized;
bool operator==(const ExternalEditor & other) const;

View File

@ -1779,8 +1779,8 @@ void Preferences::storePreferences()
moptions.externalEditorIndex = -1;
for (unsigned i = 0; i < editors.size(); i++) {
moptions.externalEditors[i] = (ExternalEditor(
editors[i].name, editors[i].command, editors[i].icon_serialized));
if (editors[i].other_data) {
editors[i].name, editors[i].command, editors[i].native_command, editors[i].icon_serialized));
if (editors[i].other_data.selected) {
// The current editor was marked before the list was edited. We
// found the mark, so this is the editor that was active.
moptions.externalEditorIndex = i;
@ -2064,12 +2064,11 @@ void Preferences::fillPreferences()
std::vector<ExternalEditorPreferences::EditorInfo> editorInfos;
for (const auto &editor : moptions.externalEditors) {
editorInfos.push_back(ExternalEditorPreferences::EditorInfo(
editor.name, editor.command, editor.icon_serialized));
editorInfos.emplace_back(editor.name, editor.command, editor.icon_serialized, editor.native_command);
}
if (moptions.externalEditorIndex >= 0) {
// Mark the current editor so we can track it.
editorInfos[moptions.externalEditorIndex].other_data = (void *)1;
editorInfos[moptions.externalEditorIndex].other_data.selected = true;
}
externalEditors->setEditors(editorInfos);
@ -2569,7 +2568,10 @@ void Preferences::workflowUpdate()
}
if (changed) {
// Update the send to external editor widget.
parent->updateExternalEditorWidget(moptions.externalEditorIndex, moptions.externalEditors);
int selected_index = moptions.externalEditorIndex >= 0
? moptions.externalEditorIndex
: static_cast<int>(moptions.externalEditors.size());
parent->updateExternalEditorWidget(selected_index, moptions.externalEditors);
}
if (moptions.cloneFavoriteTools != options.cloneFavoriteTools ||