summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKjell Ahlstedt <kjellahlstedt@gmail.com>2017-06-16 13:28:19 +0200
committerKjell Ahlstedt <kjellahlstedt@gmail.com>2017-06-16 13:28:19 +0200
commitea200a1a7254391a3e5cd68d8cd8c7a308990389 (patch)
treef86cb1d94d22e1a9b732d2a87c6999c63f420570
parentad8c8f8ed1bb64837cc007d0f034a78481bbc6ca (diff)
downloadglibmm-ea200a1a7254391a3e5cd68d8cd8c7a308990389.tar.gz
Gio::Application: Remove local class ExtraApplicationData
ExtraApplicationData is not necessary, if g_application_add_main_option() is used for options without a callback slot, and some data is added to the local class OptionArgCallbackData.
-rw-r--r--gio/src/application.ccg151
-rw-r--r--gio/src/application.hg14
2 files changed, 71 insertions, 94 deletions
diff --git a/gio/src/application.ccg b/gio/src/application.ccg
index e6bc3d29..b344c297 100644
--- a/gio/src/application.ccg
+++ b/gio/src/application.ccg
@@ -28,33 +28,6 @@ using Flags = Gio::Application::Flags;
namespace // anonymous
{
-// TODO: At the next ABI break, implement the pimpl idiom. Then we need not use
-// a GQuark for ExtraApplicationData, which should be renamed to
-// struct Gio::Application::Impl.
-// These are new data members that can't be added to Gio::Application now,
-// because it would break ABI.
-struct ExtraApplicationData
-{
- std::vector<gchar*> option_entry_strings;
-
- ~ExtraApplicationData()
- {
- for (auto str : option_entry_strings)
- {
- g_free(str);
- }
- }
-};
-
-GQuark quark_extra_application_data =
- g_quark_from_static_string("glibmm__Gio::Application::quark_extra_application_data");
-
-void
-Application_delete_extra_application_data(gpointer data)
-{
- ExtraApplicationData* extra_application_data = static_cast<ExtraApplicationData*>(data);
- delete extra_application_data;
-}
static void
Application_signal_open_callback(
@@ -141,26 +114,41 @@ static const Glib::SignalProxyInfo Application_signal_open_info = { "open",
class OptionArgCallbackData
{
public:
- explicit OptionArgCallbackData(const Gio::Application* application, gchar short_name,
+ explicit OptionArgCallbackData(const Gio::Application* application,
+ const Glib::ustring& long_name, gchar short_name,
+ const Glib::ustring& description, const Glib::ustring& arg_description,
const Glib::OptionGroup::SlotOptionArgString& slot)
- : application_(application),
+ :
+ application_(application),
+ long_name_(g_strdup(long_name.c_str())), // must not be nullptr
short_name_(short_name),
+ description_(g_strdup(Glib::c_str_or_nullptr(description))),
+ arg_description_(g_strdup(Glib::c_str_or_nullptr(arg_description))),
slot_string_(new Glib::OptionGroup::SlotOptionArgString(slot)),
slot_filename_(nullptr)
{
}
- explicit OptionArgCallbackData(const Gio::Application* application, gchar short_name,
+ explicit OptionArgCallbackData(const Gio::Application* application,
+ const Glib::ustring& long_name, gchar short_name,
+ const Glib::ustring& description, const Glib::ustring& arg_description,
const Glib::OptionGroup::SlotOptionArgFilename& slot)
- : application_(application),
+ :
+ application_(application),
+ long_name_(g_strdup(long_name.c_str())), // must not be nullptr
short_name_(short_name),
+ description_(g_strdup(Glib::c_str_or_nullptr(description))),
+ arg_description_(g_strdup(Glib::c_str_or_nullptr(arg_description))),
slot_string_(nullptr),
slot_filename_(new Glib::OptionGroup::SlotOptionArgFilename(slot))
{
}
const Gio::Application* get_application() const { return application_; }
+ const gchar* get_long_name() const { return long_name_; }
gchar get_short_name() const { return short_name_; }
+ const gchar* get_description() const { return description_; }
+ const gchar* get_arg_description() const { return arg_description_; }
bool is_filename_option() const { return slot_filename_ != nullptr; }
const Glib::OptionGroup::SlotOptionArgString* get_slot_string() const { return slot_string_; }
@@ -172,6 +160,9 @@ public:
~OptionArgCallbackData()
{
+ g_free(long_name_);
+ g_free(description_);
+ g_free(arg_description_);
delete slot_string_;
delete slot_filename_;
// Don't delete application_. It's not owned by this class.
@@ -179,15 +170,19 @@ public:
private:
const Gio::Application* application_;
+ gchar* long_name_;
gchar short_name_;
+ gchar* description_;
+ gchar* arg_description_;
// One of these slot pointers is nullptr and the other one points to a slot.
Glib::OptionGroup::SlotOptionArgString* slot_string_;
Glib::OptionGroup::SlotOptionArgFilename* slot_filename_;
// Not copyable
- OptionArgCallbackData(const OptionArgCallbackData&);
- OptionArgCallbackData& operator=(const OptionArgCallbackData&);
-};
+ OptionArgCallbackData(const OptionArgCallbackData&) = delete;
+ OptionArgCallbackData& operator=(const OptionArgCallbackData&) = delete;
+
+}; // end class OptionArgCallbackData
using OptionArgCallbackDataMap = std::map<Glib::ustring, OptionArgCallbackData*>;
OptionArgCallbackDataMap option_arg_callback_data;
@@ -398,8 +393,11 @@ Application::add_main_option_entry(OptionType arg_type, const Glib::ustring& lon
gchar short_name, const Glib::ustring& description, const Glib::ustring& arg_description,
Glib::OptionEntry::Flags flags)
{
- add_main_option_entry_private(
- (GOptionArg)arg_type, long_name, short_name, description, arg_description, flags);
+ // g_application_add_main_option() saves copies of the strings.
+ // No need to keep copies in Gio::Application.
+ g_application_add_main_option(gobj(), long_name.c_str(), short_name,
+ static_cast<GOptionFlags>(flags), static_cast<GOptionArg>(arg_type),
+ description.c_str(), Glib::c_str_or_nullptr(arg_description));
}
void
@@ -407,18 +405,21 @@ Application::add_main_option_entry(const Glib::OptionGroup::SlotOptionArgString&
const Glib::ustring& long_name, gchar short_name, const Glib::ustring& description,
const Glib::ustring& arg_description, Glib::OptionEntry::Flags flags)
{
+ OptionArgCallbackData* callback_data = nullptr;
{
std::lock_guard<std::mutex> lock(option_arg_callback_data_mutex);
OptionArgCallbackDataMap::iterator iterFind = option_arg_callback_data.find(long_name);
if (iterFind != option_arg_callback_data.end())
return; // Ignore duplicates
- auto callback_data = new OptionArgCallbackData(this, short_name, slot);
+ callback_data = new OptionArgCallbackData(
+ this, long_name, short_name, description, arg_description, slot);
option_arg_callback_data[long_name] = callback_data;
} // option_arg_callback_data_mutex.unlock()
- add_main_option_entry_private(G_OPTION_ARG_CALLBACK, long_name, short_name, description,
- arg_description, flags & ~Glib::OptionEntry::Flags::FILENAME);
+ add_main_option_entry_private(callback_data->get_long_name(), short_name,
+ callback_data->get_description(), callback_data->get_arg_description(),
+ flags & ~Glib::OptionEntry::Flags::FILENAME);
}
void
@@ -426,25 +427,31 @@ Application::add_main_option_entry_filename(const Glib::OptionGroup::SlotOptionA
const Glib::ustring& long_name, gchar short_name, const Glib::ustring& description,
const Glib::ustring& arg_description, Glib::OptionEntry::Flags flags)
{
+ OptionArgCallbackData* callback_data = nullptr;
{
std::lock_guard<std::mutex> lock(option_arg_callback_data_mutex);
OptionArgCallbackDataMap::iterator iterFind = option_arg_callback_data.find(long_name);
if (iterFind != option_arg_callback_data.end())
return; // Ignore duplicates
- auto callback_data = new OptionArgCallbackData(this, short_name, slot);
+ callback_data = new OptionArgCallbackData(
+ this, long_name, short_name, description, arg_description, slot);
option_arg_callback_data[long_name] = callback_data;
} // option_arg_callback_data_mutex.unlock()
- add_main_option_entry_private(G_OPTION_ARG_CALLBACK, long_name, short_name, description,
- arg_description, flags | Glib::OptionEntry::Flags::FILENAME);
+ add_main_option_entry_private(callback_data->get_long_name(), short_name,
+ callback_data->get_description(), callback_data->get_arg_description(),
+ flags | Glib::OptionEntry::Flags::FILENAME);
}
void
-Application::add_main_option_entry_private(GOptionArg arg, const Glib::ustring& long_name,
- gchar short_name, const Glib::ustring& description, const Glib::ustring& arg_description,
- Glib::OptionEntry::Flags flags)
+Application::add_main_option_entry_private(const gchar* long_name,
+ gchar short_name, const gchar* description,
+ const gchar* arg_description, Glib::OptionEntry::Flags flags)
{
+ // g_application_add_main_option() can't be used for options with
+ // a callback slot, because GOptionEntry.arg_data must be non-null.
+
// Create a temporary array, just so we can give the correct thing to
// g_application_add_main_option_entries():
GOptionEntry array[2];
@@ -453,51 +460,25 @@ Application::add_main_option_entry_private(GOptionArg arg, const Glib::ustring&
// g_application_add_main_option_entries() does not take its own copy
// of the strings. We must keep them alive, and keep pointers to them,
// so we can delete them when the Application instance is deleted.
-
- // GOptionEntry.long_name must be set, even if it's an empty string.
- gchar* lname = g_strdup(long_name.c_str());
- gchar* desc = description.empty() ? nullptr : g_strdup(description.c_str());
- gchar* arg_desc = arg_description.empty() ? nullptr : g_strdup(arg_description.c_str());
-
- ExtraApplicationData* extra_application_data =
- static_cast<ExtraApplicationData*>(g_object_get_qdata(gobject_, quark_extra_application_data));
- if (!extra_application_data)
- {
- extra_application_data = new ExtraApplicationData();
- g_object_set_qdata_full(gobject_, quark_extra_application_data, extra_application_data,
- Application_delete_extra_application_data);
- }
-
- extra_application_data->option_entry_strings.emplace_back(lname);
- if (desc)
- extra_application_data->option_entry_strings.emplace_back(desc);
- if (arg_desc)
- extra_application_data->option_entry_strings.emplace_back(arg_desc);
+ // This is handled in OptionArgCallbackData.
// Fill in array[0].
- array[0].arg = arg;
- array[0].long_name = lname;
+ array[0].arg = G_OPTION_ARG_CALLBACK;
+ array[0].long_name = long_name;
array[0].short_name = short_name;
- array[0].description = desc;
- array[0].arg_description = arg_desc;
+ array[0].description = description;
+ array[0].arg_description = arg_description;
array[0].flags = static_cast<int>(flags);
- if (arg == G_OPTION_ARG_CALLBACK)
- {
- // GoptionEntry.arg_data is a function pointer, cast to void*.
- // See Glib::OptionGroup::CppOptionEntry::allocate_c_arg() for a discussion
- // of this hack.
- union {
- void* dp;
- GOptionArgFunc fp;
- } u;
- u.fp = &Application_option_arg_callback;
- array[0].arg_data = u.dp;
- }
- else
- // We ensure that this is null to ensure that it is not used,
- // telling GApplication to put the parsed value in the options VariantDict instead.
- array[0].arg_data = nullptr;
+ // GoptionEntry.arg_data is a function pointer, cast to void*.
+ // See Glib::OptionGroup::CppOptionEntry::allocate_c_arg() for a discussion
+ // of this hack.
+ union {
+ void* dp;
+ GOptionArgFunc fp;
+ } u;
+ u.fp = &Application_option_arg_callback;
+ array[0].arg_data = u.dp;
g_application_add_main_option_entries(gobj(), array);
}
diff --git a/gio/src/application.hg b/gio/src/application.hg
index 90ce0115..3042a799 100644
--- a/gio/src/application.hg
+++ b/gio/src/application.hg
@@ -237,11 +237,7 @@ public:
gchar short_name = '\0', const Glib::ustring& description = Glib::ustring(),
const Glib::ustring& arg_description = Glib::ustring(),
Glib::OptionEntry::Flags flags = Glib::OptionEntry::Flags::NONE);
- _IGNORE(g_application_add_main_option_entries)
-
- //g_application_add_main_option() seems to be just a new convenience function,
- //TODO: Use it for some of our add_main_option_entry(without slot) implementation.
- _IGNORE(g_application_add_main_option)
+ _IGNORE(g_application_add_main_option_entries, g_application_add_main_option)
/** Adds a main option entry to be handled by the Application.
*
@@ -433,10 +429,10 @@ private:
*/
const Glib::Class& custom_class_init();
- // Code, common to the public add_main_option_entry*() methods.
- void add_main_option_entry_private(GOptionArg arg, const Glib::ustring& long_name,
- gchar short_name, const Glib::ustring& description,
- const Glib::ustring& arg_description, Glib::OptionEntry::Flags flags);
+ // Code, common to the public add_main_option_entry*() methods with a callback slot.
+ void add_main_option_entry_private(const gchar* long_name, gchar short_name,
+ const gchar* description, const gchar* arg_description,
+ Glib::OptionEntry::Flags flags);
};
} // namespace Gio