Fix storage of external editor icons

De-serialize and serialize icons instead of using their names.
This commit is contained in:
Lawrence Lee
2021-08-14 17:11:07 -07:00
parent d3e524a491
commit 672d6302f3
7 changed files with 75 additions and 31 deletions

View File

@@ -2522,8 +2522,22 @@ void EditorPanel::updateExternalEditorWidget(int selectedIndex, const std::vecto
// Add the editors. // Add the editors.
for (unsigned i = 0; i < editors.size(); i++) { for (unsigned i = 0; i < editors.size(); i++) {
const auto & name = editors[i].name.empty() ? Glib::ustring(" ") : editors[i].name; const auto & name = editors[i].name.empty() ? Glib::ustring(" ") : editors[i].name;
if (!editors[i].icon_name.empty()) { if (!editors[i].icon_serialized.empty()) {
Glib::RefPtr<Gio::Icon> gioIcon = Gio::Icon::create(editors[i].icon_name); 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->insertEntry(i, gioIcon, name);
} else { } else {
send_to_external->insertEntry(i, "palette-brush.png", name); send_to_external->insertEntry(i, "palette-brush.png", name);

View File

@@ -16,6 +16,8 @@
* 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 <https://www.gnu.org/licenses/>. * along with RawTherapee. If not, see <https://www.gnu.org/licenses/>.
*/ */
#include <iostream>
#include "externaleditorpreferences.h" #include "externaleditorpreferences.h"
#include "multilangmgr.h" #include "multilangmgr.h"
#include "rtimage.h" #include "rtimage.h"
@@ -85,11 +87,11 @@ ExternalEditorPreferences::getEditors() const
for (auto rowIter = children.begin(); rowIter != children.end(); rowIter++) { for (auto rowIter = children.begin(); rowIter != children.end(); rowIter++) {
const Gio::Icon *const icon = rowIter->get_value(model_columns.icon).get(); const Gio::Icon *const icon = rowIter->get_value(model_columns.icon).get();
const auto &icon_name = icon == nullptr ? "" : icon->to_string(); const auto &icon_serialized = icon == nullptr ? "" : icon->serialize().print();
editors.push_back(ExternalEditorPreferences::EditorInfo( editors.push_back(ExternalEditorPreferences::EditorInfo(
rowIter->get_value(model_columns.name), rowIter->get_value(model_columns.name),
rowIter->get_value(model_columns.command), rowIter->get_value(model_columns.command),
icon_name, icon_serialized,
rowIter->get_value(model_columns.other_data) rowIter->get_value(model_columns.other_data)
)); ));
} }
@@ -104,8 +106,28 @@ void ExternalEditorPreferences::setEditors(
for (const ExternalEditorPreferences::EditorInfo & editor : editors) { for (const ExternalEditorPreferences::EditorInfo & editor : editors) {
auto row = *list_model->append(); auto row = *list_model->append();
Glib::RefPtr<Gio::Icon> icon;
// Get icon.
if (editor.icon_serialized.empty()) {
icon = Glib::RefPtr<Gio::Icon>();
} else {
GError *e = nullptr;
GVariant *icon_variant = g_variant_parse(
nullptr, editor.icon_serialized.c_str(), nullptr, nullptr, &e);
if (e) {
std::cerr
<< "Error loading external editor icon from \""
<< editor.icon_serialized << "\": " << e->message
<< std::endl;
icon = Glib::RefPtr<Gio::Icon>();
} else {
icon = Gio::Icon::deserialize(Glib::VariantBase(icon_variant));
}
}
row[model_columns.name] = editor.name; row[model_columns.name] = editor.name;
row[model_columns.icon] = editor.icon_name.empty() ? Glib::RefPtr<Gio::Icon>() : Gio::Icon::create(editor.icon_name); row[model_columns.icon] = icon;
row[model_columns.command] = editor.command; row[model_columns.command] = editor.command;
row[model_columns.other_data] = editor.other_data; row[model_columns.other_data] = editor.other_data;
} }
@@ -247,8 +269,8 @@ void ExternalEditorPreferences::updateToolbarSensitivity()
} }
ExternalEditorPreferences::EditorInfo::EditorInfo( ExternalEditorPreferences::EditorInfo::EditorInfo(
Glib::ustring name, Glib::ustring command, Glib::ustring icon_name, void *other_data Glib::ustring name, Glib::ustring command, Glib::ustring icon_serialized, void *other_data
) : name(name), icon_name(icon_name), command(command), other_data(other_data) ) : name(name), icon_serialized(icon_serialized), command(command), other_data(other_data)
{ {
} }

View File

@@ -41,7 +41,7 @@ public:
explicit EditorInfo( explicit EditorInfo(
Glib::ustring name = Glib::ustring(), Glib::ustring name = Glib::ustring(),
Glib::ustring command = Glib::ustring(), Glib::ustring command = Glib::ustring(),
Glib::ustring icon_name = Glib::ustring(), Glib::ustring icon_serialized = Glib::ustring(),
void *other_data = nullptr void *other_data = nullptr
); );
/** /**
@@ -49,9 +49,9 @@ public:
*/ */
Glib::ustring name; Glib::ustring name;
/** /**
* The string representation of the icon. See Gio::Icon::to_string(). * The string representation of the icon. See Gio::Icon::serialize().
*/ */
Glib::ustring icon_name; Glib::ustring icon_serialized;
/** /**
* The commandline for running the program. See * The commandline for running the program. See
* Gio::AppInfo::get_commandline() * Gio::AppInfo::get_commandline()

View File

@@ -859,7 +859,7 @@ void Options::readFromFile(Glib::ustring fname)
if (keyFile.has_group("External Editor")) { if (keyFile.has_group("External Editor")) {
if (keyFile.has_key("External Editor", "Names") if (keyFile.has_key("External Editor", "Names")
|| keyFile.has_key("External Editor", "Commands") || keyFile.has_key("External Editor", "Commands")
|| keyFile.has_key("External Editor", "IconNames")) { || keyFile.has_key("External Editor", "IconsSerialized")) {
// Multiple external editors. // Multiple external editors.
const auto & names = const auto & names =
@@ -872,21 +872,21 @@ void Options::readFromFile(Glib::ustring fname)
std::vector<Glib::ustring>() : std::vector<Glib::ustring>() :
static_cast<std::vector<Glib::ustring>>( static_cast<std::vector<Glib::ustring>>(
keyFile.get_string_list("External Editor", "Commands")); keyFile.get_string_list("External Editor", "Commands"));
const auto & icon_names = const auto & icons_serialized =
!keyFile.has_key("External Editor", "IconNames") ? !keyFile.has_key("External Editor", "IconsSerialized") ?
std::vector<Glib::ustring>() : std::vector<Glib::ustring>() :
static_cast<std::vector<Glib::ustring>>( static_cast<std::vector<Glib::ustring>>(
keyFile.get_string_list("External Editor", "IconNames")); keyFile.get_string_list("External Editor", "IconsSerialized"));
externalEditors = std::vector<ExternalEditor>(std::max(std::max( externalEditors = std::vector<ExternalEditor>(std::max(std::max(
names.size(), commands.size()), icon_names.size())); names.size(), commands.size()), icons_serialized.size()));
for (unsigned i = 0; i < names.size(); i++) { for (unsigned i = 0; i < names.size(); i++) {
externalEditors[i].name = names[i]; externalEditors[i].name = names[i];
} }
for (unsigned i = 0; i < commands.size(); i++) { for (unsigned i = 0; i < commands.size(); i++) {
externalEditors[i].command = commands[i]; externalEditors[i].command = commands[i];
} }
for (unsigned i = 0; i < icon_names.size(); i++) { for (unsigned i = 0; i < icons_serialized.size(); i++) {
externalEditors[i].icon_name = icon_names[i]; externalEditors[i].icon_serialized = icons_serialized[i];
} }
if (keyFile.has_key("External Editor", "EditorIndex")) { if (keyFile.has_key("External Editor", "EditorIndex")) {
@@ -903,6 +903,9 @@ void Options::readFromFile(Glib::ustring fname)
editorToSendTo = keyFile.get_integer("External Editor", "EditorKind"); editorToSendTo = keyFile.get_integer("External Editor", "EditorKind");
#ifdef WIN32 #ifdef WIN32
auto getIconSerialized = [](const Glib::ustring &executable) {
return Glib::ustring::compose("('themed', <['%1,0', '%1,0-symbolic']>)", executable);
};
Glib::ustring gimpDir = ""; Glib::ustring gimpDir = "";
if (keyFile.has_key("External Editor", "GimpDir")) { if (keyFile.has_key("External Editor", "GimpDir")) {
gimpDir = keyFile.get_string("External Editor", "GimpDir"); gimpDir = keyFile.get_string("External Editor", "GimpDir");
@@ -912,7 +915,7 @@ void Options::readFromFile(Glib::ustring fname)
if (editorToSendTo == 1) { if (editorToSendTo == 1) {
externalEditorIndex = externalEditors.size(); externalEditorIndex = externalEditors.size();
} }
externalEditors.push_back(ExternalEditor("GIMP", "\"" + executable + "\"", executable + ",0")); externalEditors.push_back(ExternalEditor("GIMP", "\"" + executable + "\"", getIconSerialized(executable)));
} else { } else {
for (auto ver = 12; ver >= 0; --ver) { for (auto ver = 12; ver >= 0; --ver) {
executable = Glib::build_filename(gimpDir, "bin", Glib::ustring::compose(Glib::ustring("gimp-2.%1.exe"), ver)); executable = Glib::build_filename(gimpDir, "bin", Glib::ustring::compose(Glib::ustring("gimp-2.%1.exe"), ver));
@@ -920,7 +923,7 @@ void Options::readFromFile(Glib::ustring fname)
if (editorToSendTo == 1) { if (editorToSendTo == 1) {
externalEditorIndex = externalEditors.size(); externalEditorIndex = externalEditors.size();
} }
externalEditors.push_back(ExternalEditor("GIMP", "\"" + executable + "\"", executable + ",0")); externalEditors.push_back(ExternalEditor("GIMP", "\"" + executable + "\"", getIconSerialized(executable)));
break; break;
} }
} }
@@ -935,7 +938,7 @@ void Options::readFromFile(Glib::ustring fname)
if (editorToSendTo == 2) { if (editorToSendTo == 2) {
externalEditorIndex = externalEditors.size(); externalEditorIndex = externalEditors.size();
} }
externalEditors.push_back(ExternalEditor("Photoshop", "\"" + executable + "\"", executable + ",0")); externalEditors.push_back(ExternalEditor("Photoshop", "\"" + executable + "\"", getIconSerialized(executable)));
} }
if (keyFile.has_key("External Editor", "CustomEditor")) { if (keyFile.has_key("External Editor", "CustomEditor")) {
@@ -2296,17 +2299,17 @@ void Options::saveToFile(Glib::ustring fname)
{ {
std::vector<Glib::ustring> names; std::vector<Glib::ustring> names;
std::vector<Glib::ustring> commands; std::vector<Glib::ustring> commands;
std::vector<Glib::ustring> icon_names; std::vector<Glib::ustring> icons_serialized;
for (const auto & editor : externalEditors) { for (const auto & editor : externalEditors) {
names.push_back(editor.name); names.push_back(editor.name);
commands.push_back(editor.command); commands.push_back(editor.command);
icon_names.push_back(editor.icon_name); icons_serialized.push_back(editor.icon_serialized);
} }
keyFile.set_string_list("External Editor", "Names", names); keyFile.set_string_list("External Editor", "Names", names);
keyFile.set_string_list("External Editor", "Commands", commands); keyFile.set_string_list("External Editor", "Commands", commands);
keyFile.set_string_list("External Editor", "IconNames", icon_names); keyFile.set_string_list("External Editor", "IconsSerialized", icons_serialized);
keyFile.set_integer("External Editor", "EditorIndex", externalEditorIndex); keyFile.set_integer("External Editor", "EditorIndex", externalEditorIndex);
} }
@@ -2978,12 +2981,12 @@ Glib::ustring Options::getICCProfileCopyright()
ExternalEditor::ExternalEditor() {} ExternalEditor::ExternalEditor() {}
ExternalEditor::ExternalEditor( ExternalEditor::ExternalEditor(
const Glib::ustring &name, const Glib::ustring &command, const Glib::ustring &icon_name const Glib::ustring &name, const Glib::ustring &command, const Glib::ustring &icon_serialized
): name(name), command(command), icon_name(icon_name) {} ): name(name), command(command), icon_serialized(icon_serialized) {}
bool ExternalEditor::operator==(const ExternalEditor &other) const bool ExternalEditor::operator==(const ExternalEditor &other) const
{ {
return this->name == other.name && this->command == other.command && this->icon_name == other.icon_name; return this->name == other.name && this->command == other.command && this->icon_serialized == other.icon_serialized;
} }
bool ExternalEditor::operator!=(const ExternalEditor &other) const bool ExternalEditor::operator!=(const ExternalEditor &other) const

View File

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

View File

@@ -1793,7 +1793,7 @@ void Preferences::storePreferences()
moptions.externalEditorIndex = -1; moptions.externalEditorIndex = -1;
for (unsigned i = 0; i < editors.size(); i++) { for (unsigned i = 0; i < editors.size(); i++) {
moptions.externalEditors[i] = (ExternalEditor( moptions.externalEditors[i] = (ExternalEditor(
editors[i].name, editors[i].command, editors[i].icon_name)); editors[i].name, editors[i].command, editors[i].icon_serialized));
if (editors[i].other_data) { if (editors[i].other_data) {
// The current editor was marked before the list was edited. We // The current editor was marked before the list was edited. We
// found the mark, so this is the editor that was active. // found the mark, so this is the editor that was active.
@@ -2100,7 +2100,7 @@ void Preferences::fillPreferences()
std::vector<ExternalEditorPreferences::EditorInfo> editorInfos; std::vector<ExternalEditorPreferences::EditorInfo> editorInfos;
for (const auto &editor : moptions.externalEditors) { for (const auto &editor : moptions.externalEditors) {
editorInfos.push_back(ExternalEditorPreferences::EditorInfo( editorInfos.push_back(ExternalEditorPreferences::EditorInfo(
editor.name, editor.command, editor.icon_name)); editor.name, editor.command, editor.icon_serialized));
} }
if (moptions.externalEditorIndex >= 0) { if (moptions.externalEditorIndex >= 0) {
// Mark the current editor so we can track it. // Mark the current editor so we can track it.

View File

@@ -294,7 +294,12 @@ Glib::RefPtr<Gdk::Pixbuf> RTImage::createPixbufFromFile (const Glib::ustring& fi
Glib::RefPtr<Gdk::Pixbuf> RTImage::createPixbufFromGIcon(const Glib::RefPtr<const Gio::Icon> &icon, int size) Glib::RefPtr<Gdk::Pixbuf> RTImage::createPixbufFromGIcon(const Glib::RefPtr<const Gio::Icon> &icon, int size)
{ {
// TODO: Listen for theme changes and update icon, remove from cache. // TODO: Listen for theme changes and update icon, remove from cache.
return Gtk::IconTheme::get_default()->lookup_icon(icon, size, Gtk::ICON_LOOKUP_FORCE_SIZE).load_icon(); Gtk::IconInfo iconInfo = Gtk::IconTheme::get_default()->lookup_icon(icon, size, Gtk::ICON_LOOKUP_FORCE_SIZE);
try {
return iconInfo.load_icon();
} catch (Glib::Exception &e) {
return Glib::RefPtr<Gdk::Pixbuf>();
}
} }
Cairo::RefPtr<Cairo::ImageSurface> RTImage::createImgSurfFromFile (const Glib::ustring& fileName) Cairo::RefPtr<Cairo::ImageSurface> RTImage::createImgSurfFromFile (const Glib::ustring& fileName)