mkdir $(CopyDir)
mkdir $(CopyDir)\bin
copy $(BinDir)\glibmm-vc$(VSVer)0-$(ApiMajorVersion)_$(ApiMinorVersion).dll $(CopyDir)\bin
+copy $(BinDir)\glibmm-vc$(VSVer)0-$(ApiMajorVersion)_$(ApiMinorVersion).pdb $(CopyDir)\bin
copy $(BinDir)\giomm-vc$(VSVer)0-$(ApiMajorVersion)_$(ApiMinorVersion).dll $(CopyDir)\bin
+copy $(BinDir)\giomm-vc$(VSVer)0-$(ApiMajorVersion)_$(ApiMinorVersion).pdb $(CopyDir)\bin
mkdir $(CopyDir)\lib\glibmm-$(ApiMajorVersion).$(ApiMinorVersion)\include
mkdir $(CopyDir)\lib\giomm-$(ApiMajorVersion).$(ApiMinorVersion)\include
-2.51.1.1:
+2.51.1.2 (unstable):
+Distro packagers should probably not package this yet.
+
+Glib:
+* Remove some deprecated API
+ (Kjell Ahlstedt)
+* Variant: Remove the string specializations of cast_dynamic.
+ (Kjell Ahlstedt)
+* Glib::VariantType: Add get_item_types(), removing first() and
+ next().
+ (Kjell Ahlstedt) Bug #775741
+
+
+Gio:
+* init(): Set the global locale.
+ (Kjell Ahlstedt) Bug #661588
+* ActionBase: get_state_hint_variant() now returns VariantContainerBase.
+ (Kjell Ahlstedt)
+* ActionMap: add_action_with_parameter(): Register the parameter type,
+ to make this work.
+ (Daniel Boles) Bug #774444
+* ActionResult: Add is_tagged_vfunc().
+ (Kjell Ahlstedt)
+* Glib::Dispatcher: Implement the pimpl idiom
+ (Kjell Ahlstedt) Bug #651942
+* File, FileInfo, FileIOStream, FileOutputStream: Use Glib::ustring for
+ (UTF-8) file attributes of string type.
+ (Kjell Ahlstedt) Bug #615950
+* NetworkMonitor: Derive from Gio::Initable.
+ (Kjell Ahlstedt)
+* RemoteActionGroup: Rename some vfuncs to add _full().
+ (Murray Cumming)
+
+Documentation:
+* ActionMap:
+ - ActivateSlot: Mention add_action_bool().
+ - ActivateWithParameterSlot: Be more specific.
+ (Daniel Boles) Bug #774444
+
+Build:
+* Update the Visual Studio project files.
+ (Chun-wei Fan)
+* Some minor cppcheck fixes.
+ (Murray Cumming)
+
+
+2.51.1.1 (unstable):
General:
* Remove no_default_handler in some _WRAP_SIGNAL()s
(Murray Cumming)
-2.51.1:
+2.51.1 (unstable):
This is the first release of the glibmm-2.52 API/ABI.
It installs in parallel with the gtkmm-2.4 API/ABI, of which
## You should have received a copy of the GNU Lesser General Public License
## along with this library. If not, see <http://www.gnu.org/licenses/>.
-AC_INIT([glibmm], [2.51.1.1],
+AC_INIT([glibmm], [2.51.1.2],
[http://bugzilla.gnome.org/enter_bug.cgi?product=glibmm],
[glibmm], [http://www.gtkmm.org/])
AC_PREREQ([2.59])
class ChildWatch : public sigc::trackable
{
public:
- ChildWatch(const Glib::RefPtr<Glib::MainLoop>& mainLoop) : m_mainLoop(mainLoop) {}
+ explicit ChildWatch(const Glib::RefPtr<Glib::MainLoop>& mainLoop) : m_mainLoop(mainLoop) {}
void on_child_exited(GPid pid, int status);
void run(); // fork a child and call signal_child_watch
class JoinAndDelete
{
public:
- void operator()(std::thread* thread)
+ void operator()(std::thread* thread) const
{
stop_thread = true;
cond_thread.notify_all();
class JoinAndDelete
{
public:
- void operator()(std::thread* thread)
+ void operator()(std::thread* thread) const
{
stop_thread = true;
cond_thread.notify_all();
template <typename T_Value>
void get_state_hint(T_Value& value) const;
- //TODO: When we can break ABI, Return a Glib::VariantContainerBase,
- // as we already do for ActionGroup::get_action_state_hint(),
- // because that is what this returns (to specify a range).
- _WRAP_METHOD(Glib::VariantBase get_state_hint_variant() const, g_action_get_state_hint)
+ _WRAP_METHOD(Glib::VariantContainerBase get_state_hint_variant() const, g_action_get_state_hint)
_WRAP_METHOD(bool get_enabled() const, g_action_get_enabled)
_WRAP_METHOD(Glib::VariantType get_action_parameter_type(const Glib::ustring& action_name) const, g_action_group_get_action_parameter_type)
_WRAP_METHOD(Glib::VariantType get_action_state_type(const Glib::ustring& action_name) const, g_action_group_get_action_state_type)
-
- _WRAP_METHOD(Glib::VariantContainerBase get_action_state_hint(const Glib::ustring& action_name) const, g_action_group_get_action_state_hint, deprecated "Use the get_action_state() method that takes an output parameter instead.")
-
//TODO: How do we check for a nullptr Variant?
/**
* Requests a hint about the valid range of values for the state of the
}
Glib::RefPtr<SimpleAction>
-ActionMap::add_action_with_parameter(
- const Glib::ustring& name, const ActivateWithParameterSlot& slot)
+ActionMap::add_action(const Glib::ustring& name, const ActivateSlot& slot)
{
auto action = add_action(name);
- action->signal_activate().connect(slot);
+ action->signal_activate().connect(sigc::hide(slot));
return action;
}
Glib::RefPtr<SimpleAction>
-ActionMap::add_action(const Glib::ustring& name, const ActivateSlot& slot)
+ActionMap::add_action_with_parameter(
+ const Glib::ustring& name, const ActivateWithParameterSlot& slot, const Glib::VariantType& parameter_type)
{
- auto action = add_action(name);
- action->signal_activate().connect(sigc::hide(slot));
+ auto action = SimpleAction::create(name, parameter_type);
+ action->signal_activate().connect(slot);
return action;
}
{
_CLASS_INTERFACE(ActionMap, GActionMap, G_ACTION_MAP, GActionMapInterface)
+ // The various add_action...() methods are our equivalent for g_action_map_add_action_entries().
+ _IGNORE(g_action_map_add_action_entries)
+
public:
+ _WRAP_METHOD(void add_action(const Glib::RefPtr<Action>& action), g_action_map_add_action)
+ _WRAP_METHOD(void remove_action(const Glib::ustring& action_name), g_action_map_remove_action)
+
_WRAP_METHOD(Glib::RefPtr<Action> lookup_action(const Glib::ustring& action_name), g_action_map_lookup_action, refreturn)
_WRAP_METHOD(Glib::RefPtr<const Action> lookup_action(const Glib::ustring& action_name) const, g_action_map_lookup_action, constversion, refreturn)
- /** A Slot to be called when an action has been activated.
- * See add_action_with_parameter().
- *
- * For instance,
- * void on_slot_activated(const Glib::VariantBase& parameter);
- */
- using ActivateWithParameterSlot = sigc::slot<void(const Glib::VariantBase&)>;
- //This is an equivalent for g_action_map_add_action_entries().
/** A convenience method for creating a SimpleAction instance
* and adding it to the ActionMap.
*
*/
Glib::RefPtr<SimpleAction> add_action(const Glib::ustring& name);
- //This is an equivalent for g_action_map_add_action_entries().
+ /** A Slot to be called when an action has been activated,
+ * without passing a parameter to the slot.
+ * See add_action() and add_action_bool().
+ *
+ * For instance,
+ * void on_slot_activated();
+ */
+ using ActivateSlot = sigc::slot<void()>;
+
/** A convenience method for creating a SimpleAction instance
* and adding it to the ActionMap.
*
* @param slot The callback method to be called when the action is activated.
* @return The Action.
*/
- Glib::RefPtr<SimpleAction> add_action_with_parameter(const Glib::ustring& name, const ActivateWithParameterSlot& slot);
- _IGNORE(g_action_map_add_action_entries)
+ Glib::RefPtr<SimpleAction> add_action(const Glib::ustring& name, const ActivateSlot& slot);
+
/** A Slot to be called when an action has been activated,
- * without passing a parameter to the slot.
- * See add_action().
+ * passing a parameter of a specified type.
+ * See add_action_with_parameter().
*
* For instance,
- * void on_slot_activated();
+ * void on_slot_activated(const Glib::VariantBase& parameter);
*/
- using ActivateSlot = sigc::slot<void()>;
+ using ActivateWithParameterSlot = sigc::slot<void(const Glib::VariantBase&)>;
/** A convenience method for creating a SimpleAction instance
* and adding it to the ActionMap.
*
* @param name The name of the Action.
* @param slot The callback method to be called when the action is activated.
+ * @param parameter_type The type of parameter to be passed to the slot.
* @return The Action.
*/
- Glib::RefPtr<SimpleAction> add_action(const Glib::ustring& name, const ActivateSlot& slot);
+ Glib::RefPtr<SimpleAction> add_action_with_parameter(const Glib::ustring& name, const ActivateWithParameterSlot& slot, const Glib::VariantType& parameter_type);
/** A convenience method for creating a boolean-stateful SimpleAction instance
* See add_action_radio_string().
*
* For instance,
- * void on_slot_activated(const Glib::VariantBase& parameter);
+ * void on_slot_activated(const Glib::ustring& parameter);
*/
using ActivateWithStringParameterSlot = sigc::slot<void(const Glib::ustring&)>;
*/
Glib::RefPtr<SimpleAction> add_action_radio_string(const Glib::ustring& name, const ActivateWithStringParameterSlot& slot, const Glib::ustring& state);
+
//TODO: Docs: Add hints about how to specify the various possible states in the GtkBuilder XML.
/** A convenience method for creating an integer-based radio SimpleAction instance
* and adding it to the ActionMap.
Glib::RefPtr<SimpleAction> add_action_radio_integer(const Glib::ustring& name, gint32 state);
/** A Slot to be called when an action has been activated.
- * See add_action_radio_int().
+ * See add_action_radio_integer().
*
* For instance,
- * void on_slot_activated(const Glib::VariantBase& parameter);
+ * void on_slot_activated(int parameter);
*/
using ActivateWithIntParameterSlot = sigc::slot<void(int)>;
Glib::RefPtr<SimpleAction> add_action_radio_integer(const Glib::ustring& name, const ActivateWithIntParameterSlot& slot, gint32 state);
- _WRAP_METHOD(void add_action(const Glib::RefPtr<Action>& action), g_action_map_add_action)
- _WRAP_METHOD(void remove_action(const Glib::ustring& action_name), g_action_map_remove_action)
-
#m4 _CONVERSION(`Glib::RefPtr<Action>', `GAction*', `Glib::unwrap($3)')
_WRAP_VFUNC(Glib::RefPtr<Action> lookup_action(const Glib::ustring& name) const, "lookup_action", refreturn)
_WRAP_METHOD(bool is_tagged(gpointer source_tag) const, g_async_result_is_tagged)
-
- // TODO: For some reason, the compiler cannot find an unwrap() for ObjectBase.
+ // The compiler cannot find an unwrap() for ObjectBase, because
+ // ObjectBase::BaseObjectType is not declared.
//#m4 _CONVERSION(`Glib::RefPtr<Glib::ObjectBase>',`GObject*',__CONVERT_REFPTR_TO_P)
#m4 _CONVERSION(`Glib::RefPtr<Glib::ObjectBase>',`GObject*',`unwrap_objectbase_custom($3)')
- _WRAP_VFUNC(Glib::RefPtr<Glib::ObjectBase> get_source_object(),
- "get_source_object")
-
- //TODO: is_tagged() vfunc when we can break ABI.
+ _WRAP_VFUNC(Glib::RefPtr<Glib::ObjectBase> get_source_object(), "get_source_object")
+ _WRAP_VFUNC(bool is_tagged(gpointer source_tag), "is_tagged")
};
} // namespace Gio
-
bool set_attributes_finish(const Glib::RefPtr<AsyncResult>& result, const Glib::RefPtr<FileInfo>& info);
- _WRAP_METHOD(bool set_attribute_string(const std::string& attribute, const std::string& value, FileQueryInfoFlags flags, const Glib::RefPtr<Cancellable>& cancellable{?}),
+ _WRAP_METHOD(bool set_attribute_string(const std::string& attribute, const Glib::ustring& value, FileQueryInfoFlags flags, const Glib::RefPtr<Cancellable>& cancellable{?}),
g_file_set_attribute_string,
errthrow)
-// -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 2 -*-
-
/* Copyright (C) 2007 The gtkmm Development Team
*
* This library is free software; you can redistribute it and/or
_WRAP_METHOD(FileAttributeStatus get_attribute_status(const std::string& attribute) const, g_file_info_get_attribute_status)
- //TODO: This should return a ustring instead: https://bugzilla.gnome.org/show_bug.cgi?id=615950#c7
- _WRAP_METHOD(std::string get_attribute_string(const std::string& attribute) const,
+ _WRAP_METHOD(Glib::ustring get_attribute_string(const std::string& attribute) const,
g_file_info_get_attribute_string)
#m4 _CONVERSION(`char**',`std::vector<Glib::ustring>',`Glib::ArrayHandler<Glib::ustring>::array_to_vector($3, Glib::OWNERSHIP_NONE)')
_WRAP_METHOD(bool set_attribute_status(const std::string& attribute, FileAttributeStatus status), g_file_info_set_attribute_status)
- //TODO: This should take a ustring value instead: https://bugzilla.gnome.org/show_bug.cgi?id=615950#c7
- _WRAP_METHOD(void set_attribute_string(const std::string& attribute, const std::string& attr_value),
+ _WRAP_METHOD(void set_attribute_string(const std::string& attribute, const Glib::ustring& attr_value),
g_file_info_set_attribute_string)
#m4 _CONVERSION(`const std::vector<Glib::ustring>&',`char**',`const_cast<char**>(Glib::ArrayHandler<Glib::ustring>::vector_to_array($3).data())')
_WRAP_METHOD(bool is_symlink() const, g_file_info_get_is_symlink)
_WRAP_METHOD(std::string get_name() const, g_file_info_get_name)
- //TODO: This should return a ustring instead. See https://bugzilla.gnome.org/show_bug.cgi?id=615950#c4
- _WRAP_METHOD(std::string get_display_name() const, g_file_info_get_display_name)
+ _WRAP_METHOD(Glib::ustring get_display_name() const, g_file_info_get_display_name)
- //TODO: This should return a ustring instead. See https://bugzilla.gnome.org/show_bug.cgi?id=615950#c4
- _WRAP_METHOD(std::string get_edit_name() const, g_file_info_get_edit_name)
+ _WRAP_METHOD(Glib::ustring get_edit_name() const, g_file_info_get_edit_name)
_WRAP_METHOD(Glib::RefPtr<Icon> get_icon(), g_file_info_get_icon, refreturn)
_WRAP_METHOD(Glib::RefPtr<const Icon> get_icon() const, g_file_info_get_icon, refreturn, constversion)
_WRAP_METHOD(Glib::RefPtr<Icon> get_symbolic_icon(), g_file_info_get_symbolic_icon, refreturn)
_WRAP_METHOD(Glib::RefPtr<const Icon> get_symbolic_icon() const, g_file_info_get_symbolic_icon, refreturn, constversion)
- //TODO: This should return a ustring instead. See https://bugzilla.gnome.org/show_bug.cgi?id=615950#c4
- _WRAP_METHOD(std::string get_content_type() const, g_file_info_get_content_type)
+ _WRAP_METHOD(Glib::ustring get_content_type() const, g_file_info_get_content_type)
_WRAP_METHOD(goffset get_size() const, g_file_info_get_size)
_WRAP_METHOD(std::string get_symlink_target() const, g_file_info_get_symlink_target)
- //TODO: This should return a ustring instead. See https://bugzilla.gnome.org/show_bug.cgi?id=615950#c4
- _WRAP_METHOD(std::string get_etag() const, g_file_info_get_etag)
+ _WRAP_METHOD(Glib::ustring get_etag() const, g_file_info_get_etag)
_WRAP_METHOD(gint32 get_sort_order() const, g_file_info_get_sort_order)
_WRAP_METHOD(void set_attribute_mask(const Glib::RefPtr<FileAttributeMatcher>& mask),
_WRAP_METHOD(void set_is_symlink(bool symlink = true), g_file_info_set_is_symlink)
_WRAP_METHOD(void set_name(const std::string& name), g_file_info_set_name)
- //TODO: This should take a ustring instead. See https://bugzilla.gnome.org/show_bug.cgi?id=615950#c4
- _WRAP_METHOD(void set_display_name(const std::string& display_name), g_file_info_set_display_name)
+ _WRAP_METHOD(void set_display_name(const Glib::ustring& display_name), g_file_info_set_display_name)
- //TODO: This should take a ustring instead. See https://bugzilla.gnome.org/show_bug.cgi?id=615950#c4
- _WRAP_METHOD(void set_edit_name(const std::string& edit_name), g_file_info_set_edit_name)
+ _WRAP_METHOD(void set_edit_name(const Glib::ustring& edit_name), g_file_info_set_edit_name)
_WRAP_METHOD(void set_icon(const Glib::RefPtr<Icon>& icon), g_file_info_set_icon)
_WRAP_METHOD(void set_symbolic_icon(const Glib::RefPtr<Icon>& icon), g_file_info_set_symbolic_icon)
- //TODO: This should take a ustring instead. See https://bugzilla.gnome.org/show_bug.cgi?id=615950#c4
- _WRAP_METHOD(void set_content_type(const std::string& content_type), g_file_info_set_content_type)
+ _WRAP_METHOD(void set_content_type(const Glib::ustring& content_type), g_file_info_set_content_type)
_WRAP_METHOD(void set_size(goffset size), g_file_info_set_size)
-// -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 2 -*-
-
/* Copyright (C) 2007 The gtkmm Development Team
*
* This library is free software; you can redistribute it and/or
_WRAP_METHOD(Glib::RefPtr<FileInfo> query_info_finish(const Glib::RefPtr<AsyncResult>& result),
g_file_io_stream_query_info_finish,
errthrow)
- _WRAP_METHOD(std::string get_etag() const, g_file_io_stream_get_etag)
+ _WRAP_METHOD(Glib::ustring get_etag() const, g_file_io_stream_get_etag)
};
g_file_output_stream_query_info_finish,
refreturn, errthrow)
- _WRAP_METHOD(std::string get_etag() const, g_file_output_stream_get_etag)
+ _WRAP_METHOD(Glib::ustring get_etag() const, g_file_output_stream_get_etag)
};
} // namespace Gio
(return-type "GObject*")
)
+(define-vfunc is_tagged
+ (of-object "GAsyncResult")
+ (return-type "gboolean")
+ (parameters
+ '("gpointer" "source_tag")
+ )
+)
+
; GBufferedInputStream
(define-vfunc fill
{
}
+ SlotWithData(const SlotWithData& src) = delete;
+ SlotWithData& operator=(const SlotWithData& src) = delete;
+
~SlotWithData() { delete m_slot; }
void operator()() { (*m_slot)(m_data); }
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <glibmm/interface.h>
+#include <giomm/initable.h>
#include <giomm/asyncresult.h>
#include <giomm/cancellable.h>
#include <giomm/socketconnectable.h>
#include <gio/gio.h>
_DEFS(giomm,gio)
-_PINCLUDE(glibmm/private/interface_p.h)
+_PINCLUDE(giomm/private/initable_p.h)
_PINCLUDE(gio/gio.h)
#ifndef DOXYGEN_SHOULD_SKIP_THIS
*
* @newin{2,44}
*/
-class NetworkMonitor : public Glib::Interface
+class NetworkMonitor : public Initable
{
- _CLASS_INTERFACE(NetworkMonitor, GNetworkMonitor, G_NETWORK_MONITOR, GNetworkMonitorInterface)
+ _CLASS_INTERFACE(NetworkMonitor, GNetworkMonitor, G_NETWORK_MONITOR, GNetworkMonitorInterface, Initable, GInitable)
public:
_WRAP_METHOD(static Glib::RefPtr<NetworkMonitor> get_default(), g_network_monitor_get_default, newin "2,44")
#m4 _CONVERSION(`GVariant*',`const Glib::VariantBase&',`Glib::wrap($3, true)')
- _WRAP_VFUNC(void activate_action(const Glib::ustring& action_name, const Glib::VariantBase& parameter, const Glib::VariantBase& platform_data), "activate_action_full")
- _WRAP_VFUNC(void change_action_state(const Glib::ustring& action_name, const Glib::VariantBase& value, const Glib::VariantBase& platform_data), "change_action_state_full")
+ _WRAP_VFUNC(void activate_action_full(const Glib::ustring& action_name, const Glib::VariantBase& parameter, const Glib::VariantBase& platform_data), "activate_action_full")
+ _WRAP_VFUNC(void change_action_state_full(const Glib::ustring& action_name, const Glib::VariantBase& value, const Glib::VariantBase& platform_data), "change_action_state_full")
};
} // namespace Gio
#include <cerrno>
#include <fcntl.h>
#include <glib.h>
-#include <set>
+#include <forward_list>
+#include <memory>
#include <utility> // For std::move()
#ifdef G_OS_WIN32
#define EINTR 0 /* TODO: should use the real define */
#endif
+namespace Glib
+{
+class DispatchNotifier;
+}
+
namespace
{
struct DispatchNotifyData
{
- Glib::Dispatcher* dispatcher;
+ Glib::Dispatcher::Impl* dispatcher_impl;
Glib::DispatchNotifier* notifier;
- DispatchNotifyData() : dispatcher(nullptr), notifier(nullptr) {}
+ DispatchNotifyData()
+ : dispatcher_impl(nullptr), notifier(nullptr)
+ {}
- DispatchNotifyData(Glib::Dispatcher* d, Glib::DispatchNotifier* n) : dispatcher(d), notifier(n) {}
+ DispatchNotifyData(Glib::Dispatcher::Impl* d, Glib::DispatchNotifier* n)
+ : dispatcher_impl(d), notifier(n)
+ {}
};
static void
}
#endif /* !G_OS_WIN32 */
+void warn_dropped_dispatcher_message()
+{
+ g_warning("Dropped dispatcher message as the dispatcher no longer exists.");
+}
+
} // anonymous namespace
namespace Glib
{
+// The most important reason for having the dispatcher implementation in a separate
+// class is that its deletion can be delayed until it's safe to delete it.
+// Deletion is safe when the pipe does not contain any message to the dispatcher
+// to delete. When the pipe is empty, it's surely safe.
+struct Dispatcher::Impl
+{
+public:
+ sigc::signal<void()> signal_;
+ DispatchNotifier* notifier_;
+
+ explicit Impl(const Glib::RefPtr<MainContext>& context);
+
+ // noncopyable
+ Impl(const Impl&) = delete;
+ Impl& operator=(const Impl&) = delete;
+};
+
class DispatchNotifier : public sigc::trackable
{
public:
DispatchNotifier(const DispatchNotifier&) = delete;
DispatchNotifier& operator=(const DispatchNotifier&) = delete;
- static DispatchNotifier* reference_instance(
- const Glib::RefPtr<MainContext>& context, const Dispatcher* dispatcher);
- static void unreference_instance(DispatchNotifier* notifier, const Dispatcher* dispatcher);
+ static DispatchNotifier* reference_instance(const Glib::RefPtr<MainContext>& context);
+ static void unreference_instance(DispatchNotifier* notifier, Dispatcher::Impl* dispatcher_impl);
- void send_notification(Dispatcher* dispatcher);
+ void send_notification(Dispatcher::Impl* dispatcher_impl);
protected:
// Only used by reference_instance(). Should be private, but that triggers
private:
static thread_local DispatchNotifier* thread_specific_instance_;
- std::set<const Dispatcher*> deleted_dispatchers_;
-
+ using UniqueImplPtr = std::unique_ptr<Dispatcher::Impl>;
+ std::forward_list<UniqueImplPtr> orphaned_dispatcher_impl_;
long ref_count_;
Glib::RefPtr<MainContext> context_;
#ifdef G_OS_WIN32
thread_local DispatchNotifier* DispatchNotifier::thread_specific_instance_ = nullptr;
DispatchNotifier::DispatchNotifier(const Glib::RefPtr<MainContext>& context)
-: deleted_dispatchers_(),
+: orphaned_dispatcher_impl_(),
ref_count_(0),
context_(context),
#ifdef G_OS_WIN32
}
// static
-DispatchNotifier*
-DispatchNotifier::reference_instance(
- const Glib::RefPtr<MainContext>& context, const Dispatcher* dispatcher)
+DispatchNotifier* DispatchNotifier::reference_instance(
+ const Glib::RefPtr<MainContext>& context)
{
DispatchNotifier* instance = thread_specific_instance_;
{
// Prevent massive mess-up.
g_return_val_if_fail(instance->context_ == context, nullptr);
-
- // In the possible but unlikely case that a new dispatcher gets the same
- // address as a newly deleted one, if the pipe still contains messages to
- // the deleted dispatcher, those messages will be delivered to the new one.
- // Not ideal, but perhaps the best that can be done without breaking ABI.
- // The alternative would be to remove the following erase(), and risk not
- // delivering messages sent to the new dispatcher.
- // TODO: When we can break ABI, a better solution without this drawback can
- // be implemented. See https://bugzilla.gnome.org/show_bug.cgi?id=651942
- // especially comment 16.
- instance->deleted_dispatchers_.erase(dispatcher);
}
++instance->ref_count_; // initially 0
}
// static
-void
-DispatchNotifier::unreference_instance(DispatchNotifier* notifier, const Dispatcher* dispatcher)
+void DispatchNotifier::unreference_instance(
+ DispatchNotifier* notifier, Dispatcher::Impl* dispatcher_impl)
{
DispatchNotifier* const instance = thread_specific_instance_;
g_return_if_fail(instance == notifier);
if (instance->pipe_is_empty())
- // No messages in the pipe. No need to keep track of deleted dispatchers.
- instance->deleted_dispatchers_.clear();
+ {
+ // No messages in the pipe. Delete the Dispatcher::Impl immediately.
+ delete dispatcher_impl;
+ instance->orphaned_dispatcher_impl_.clear();
+ }
else
- // There are messages in the pipe, possibly to the deleted dispatcher.
- // Keep its address, so pipe_io_handler() can avoid delivering messages to it.
- instance->deleted_dispatchers_.insert(dispatcher);
+ {
+ // There are messages in the pipe, possibly to the orphaned Dispatcher::Impl.
+ // Keep it around until it can safely be deleted.
+ // Delete all slots connected to the Dispatcher. Then the signal emission
+ // in pipe_io_handler() will do nothing.
+ dispatcher_impl->signal_.clear();
+ // Add a slot that will warn that a message has been dropped.
+ dispatcher_impl->signal_.connect(sigc::ptr_fun(warn_dropped_dispatcher_message));
+ instance->orphaned_dispatcher_impl_.push_front(UniqueImplPtr(dispatcher_impl));
+ }
if (--instance->ref_count_ <= 0)
{
}
}
-void
-DispatchNotifier::send_notification(Dispatcher* dispatcher)
+void DispatchNotifier::send_notification(Dispatcher::Impl* dispatcher_impl)
{
#ifdef G_OS_WIN32
{
const std::lock_guard<std::mutex> lock(mutex_);
const bool was_empty = notify_queue_.empty();
- notify_queue_.emplace_back(DispatchNotifyData(dispatcher, this));
+ notify_queue_.emplace_back(DispatchNotifyData(dispatcher_impl, this));
if (was_empty)
{
}
#else /* !G_OS_WIN32 */
- DispatchNotifyData data(dispatcher, this);
+ DispatchNotifyData data(dispatcher_impl, this);
gssize n_written;
do
g_return_val_if_fail(data.notifier == this, true);
- // Drop the received message, if it is addressed to a deleted dispatcher.
- const bool drop_message =
- (deleted_dispatchers_.find(data.dispatcher) != deleted_dispatchers_.end());
-
- // If the pipe is empty, there can be no messages to deleted dispatchers.
- // No reason to keep track of them any more.
- if (!deleted_dispatchers_.empty() && pipe_is_empty())
- deleted_dispatchers_.clear();
-
- if (drop_message)
- {
- g_warning("Dropped dispatcher message as the dispatcher no longer exists");
- return true;
- }
-
// Actually, we wouldn't need the try/catch block because the Glib::Source
// C callback already does it for us. However, we do it anyway because the
// default return value is 'false', which is not what we want.
try
{
- data.dispatcher->signal_(); // emit
+ data.dispatcher_impl->signal_(); // emit
}
catch (...)
{
Glib::exception_handlers_invoke();
}
+ if (!orphaned_dispatcher_impl_.empty() && pipe_is_empty())
+ orphaned_dispatcher_impl_.clear();
+
return true;
}
-/**** Glib::Dispatcher *****************************************************/
+/**** Glib::Dispatcher and Glib::Dispatcher::Impl **************************/
-Dispatcher::Dispatcher()
-: signal_(), notifier_(DispatchNotifier::reference_instance(MainContext::get_default(), this))
+Dispatcher::Impl::Impl(const Glib::RefPtr<MainContext>& context)
+: signal_(),
+ notifier_(DispatchNotifier::reference_instance(context))
{
}
+Dispatcher::Dispatcher()
+: impl_(new Dispatcher::Impl(MainContext::get_default()))
+{}
+
+
Dispatcher::Dispatcher(const Glib::RefPtr<MainContext>& context)
-: signal_(), notifier_(DispatchNotifier::reference_instance(context, this))
+: impl_(new Dispatcher::Impl(context))
{
}
Dispatcher::~Dispatcher() noexcept
{
- DispatchNotifier::unreference_instance(notifier_, this);
+ DispatchNotifier::unreference_instance(impl_->notifier_, impl_);
}
void
Dispatcher::emit()
{
- notifier_->send_notification(this);
+ impl_->notifier_->send_notification(impl_);
}
void
Dispatcher::operator()()
{
- notifier_->send_notification(this);
+ impl_->notifier_->send_notification(impl_);
}
sigc::connection
Dispatcher::connect(const sigc::slot<void()>& slot)
{
- return signal_.connect(slot);
+ return impl_->signal_.connect(slot);
}
sigc::connection
Dispatcher::connect(sigc::slot<void()>&& slot)
{
- return signal_.connect(std::move(slot));
+ return impl_->signal_.connect(std::move(slot));
}
} // namespace Glib
namespace Glib
{
-#ifndef DOXYGEN_SHOULD_SKIP_THIS
-class DispatchNotifier;
-#endif
-
/** Signal class for inter-thread communication.
* @ingroup Threads
* Glib::Dispatcher works similar to sigc::signal<void()>. But unlike normal
*/
sigc::connection connect(sigc::slot<void()>&& slot);
-private:
- sigc::signal<void()> signal_;
- DispatchNotifier* notifier_;
+ #ifndef DOXYGEN_SHOULD_SKIP_THIS
+ struct Impl;
+ #endif
-#ifndef DOXYGEN_SHOULD_SKIP_THIS
- friend class Glib::DispatchNotifier;
-#endif
+private:
+ Impl* impl_; // hidden implementation
};
/*! A Glib::Dispatcher example.
#include <glibmm/init.h>
#include <glibmm/error.h>
+#include <locale>
+#include <clocale>
+#include <stdexcept>
+
+namespace
+{
+ bool init_to_users_preferred_locale = true;
+
+} // anonymous namespace
namespace Glib
{
+void set_init_to_users_preferred_locale(bool state)
+{
+ init_to_users_preferred_locale = state;
+}
+
+bool get_init_to_users_preferred_locale()
+{
+ return init_to_users_preferred_locale;
+}
-void
-init()
+void init()
{
+ static bool is_initialized = false;
+
+ if (is_initialized)
+ return;
+
+ if (init_to_users_preferred_locale)
+ {
+ try
+ {
+ // Set the global locale for C++ functions and the locale for C functions
+ // to the user-preferred locale.
+ std::locale::global(std::locale(""));
+ }
+ catch (const std::runtime_error& ex)
+ {
+ g_warning("Can't set the global locale to the user's preferred locale.\n"
+ " %s\n The environment variable LANG may be wrong.\n", ex.what());
+ }
+ }
+ else
+ {
+ try
+ {
+ // Make the C++ locale equal to the C locale.
+ std::locale::global(std::locale(std::setlocale(LC_ALL, nullptr)));
+ }
+ catch (const std::runtime_error& ex)
+ {
+ g_warning("Can't make the global C++ locale equal to the C locale.\n"
+ " %s\n C locale = %s\n", ex.what(), std::setlocale(LC_ALL, nullptr));
+ }
+ }
+
// Also calls Glib::wrap_register_init() and Glib::wrap_init().
Glib::Error::register_init();
+
+ is_initialized = true;
}
} // namespace Glib
-// -*- c++ -*-
#ifndef _GLIBMM_INIT_H
#define _GLIBMM_INIT_H
-/* $Id$ */
-
/* Copyright (C) 2002 The gtkmm Development Team
*
* This library is free software; you can redistribute it and/or
{
/** Initialize glibmm.
- * You may call this more than once.
- * You do not need to call this if you are using Glib::MainLoop or Gtk::Main,
- * because they call it for you.
+ *
+ * You may call this more than once. Calls after the first one have no effect.
+ * Sets the global locale as specified by set_init_to_users_preferred_locale().
+ * You do not need to call %Glib::init() if you are using Gtk::Application,
+ * because it calls %Glib::init() for you.
+ *
+ * @see set_init_to_users_preferred_locale()
*/
void init();
+/** Instruct Glib::init() which global locale to set.
+ *
+ * To have the intended effect, this function must be called before init() is called.
+ * Not calling it has the same effect as calling it with @a state = <tt>true</tt>.
+ *
+ * Note the confusing difference between C locale and "C" locale.
+ * The C locale is the locale used by C code, set by std::setlocale(LC_ALL, locale_name).
+ * The "C" locale is the classic locale, set by std::setlocale(LC_ALL, "C")
+ * or std::locale::global(std::locale::classic()). It's the default global locale
+ * in a C or C++ program.
+ *
+ * In a mixed C and C++ program, like a program using glibmm, having the C global
+ * locale differ from std::locale::global() is error prone. Glib::init() tries
+ * to avoid that.
+ *
+ * @param state If <tt>true</tt>, init() will set the C and C++ global locale
+ * to the user's preferred locale (std::locale::global(std::locale(""))).
+ * The user's preferred locale is set in the program's environment,
+ * usually with the LANG environment variable.<br>
+ * If <tt>false</tt>, init() will set the C++ global locale to the C global locale
+ * (std::locale::global(std::locale(std::setlocale(LC_ALL, nullptr)))).
+ *
+ * @newin{2,52}
+ */
+void set_init_to_users_preferred_locale(bool state = true);
+
+/** Get the state, set with set_init_to_users_preferred_locale().
+ * @returns The state, set with set_init_to_users_preferred_locale(); <tt>true</tt>
+ * if set_init_to_users_preferred_locale() has not been called.
+ *
+ * @newin{2,52}
+ */
+bool get_init_to_users_preferred_locale();
+
} // namespace Glib
#endif /* _GLIBMM_INIT_H */
*/
inline explicit operator bool() const noexcept;
-#ifndef GLIBMM_DISABLE_DEPRECATED
- /// @deprecated Use reset() instead because this leads to confusion with clear() methods on the
- /// underlying class. For instance, people use .clear() when they mean ->clear().
- inline void clear() noexcept;
-#endif // GLIBMM_DISABLE_DEPRECATED
-
/** Set underlying instance to nullptr, decrementing reference count of existing instance
* appropriately.
* @newin{2,16}
return (pCppObject_ != nullptr);
}
-#ifndef GLIBMM_DISABLE_DEPRECATED
-template <class T_CppObject>
-inline void
-RefPtr<T_CppObject>::clear() noexcept
-{
- reset();
-}
-#endif // GLIBMM_DISABLE_DEPRECATED
-
template <class T_CppObject>
inline void
RefPtr<T_CppObject>::reset() noexcept
* If you're using std::ostringstream to build strings for display in the
* user interface, you must convert the result back to UTF-8 as shown below:
* @code
- * std::locale::global(std::locale("")); // set the global locale to the user's preferred locale
+ * std::locale::global(std::locale("")); // Set the global locale to the user's preferred locale.
+ * // Usually unnecessary here, because Glib::init()
+ * // does it for you.
* std::ostringstream output;
* output << percentage << " % done";
* label->set_text(Glib::locale_to_utf8(output.str()));
#ifndef DOXYGEN_SHOULD_SKIP_THIS
-#ifndef GLIBMM_DISABLE_DEPRECATED
-/* Occasionally, a struct variable has to be initialized after its definition,
- * i.e. when using structs as class member data. For convenience, the macro
- * GLIBMM_INITIALIZE_STRUCT(Var, Type) is provided. It even avoids creating
- * a temporary if the compiler is GCC.
- *
- * @deprecated Use e.g. std::memset() instead.
- * It's not used any more in the code generated by _CLASS_BOXEDTYPE_STATIC.
- * It generates compiler warnings if __STRICT_ANSI__ is defined.
- */
-#if ((__GNUC__ >= 3) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)) && !defined(__STRICT_ANSI__)
-
-#define GLIBMM_INITIALIZE_STRUCT(Var, Type) __builtin_memset(&(Var), 0, sizeof(Type))
-
-#else
-
-// TODO: This causes warnings like this:
-//"missing initializer for member"
-#define GLIBMM_INITIALIZE_STRUCT(Var, Type) \
- G_STMT_START \
- { \
- Type const temp_initializer__ = { \
- 0, \
- }; \
- (Var) = temp_initializer__; \
- } \
- G_STMT_END
-
-#endif
-#endif // GLIBMM_DISABLE_DEPRECATED
-
namespace Glib
{
// These are used by gmmproc-generated type conversions:
-#ifndef GLIBMM_DISABLE_DEPRECATED
-/** Helper to deal with memory allocated
- * by GLib functions in an exception-safe manner.
- *
- * @deprecated Use make_unique_ptr_gfree() instead.
- */
-template <typename T>
-class ScopedPtr
-{
-private:
- T* ptr_;
- ScopedPtr(const ScopedPtr<T>&);
- ScopedPtr<T>& operator=(const ScopedPtr<T>&);
-
-public:
- ScopedPtr() : ptr_(nullptr) {}
- explicit ScopedPtr(T* ptr) : ptr_(ptr) {}
- ~ScopedPtr() noexcept { g_free(ptr_); }
- T* get() const { return ptr_; }
- T** addr() { return &ptr_; }
-};
-#endif // GLIBMM_DISABLE_DEPRECATED
-
/** Helper to deal with memory allocated
* by GLib functions in an exception-safe manner.
*
gobject_ = g_tree_new_full(on_compare_tree, &key_compare_slot, on_destroy_key, on_destroy_value);
}
- BalancedTree(const CompareFunc &key_compare_slot_) :
+ explicit BalancedTree(const CompareFunc &key_compare_slot_) :
key_compare_slot(key_compare_slot_)
{
gobject_ = g_tree_new_full(on_compare_tree, &key_compare_slot, on_destroy_key, on_destroy_value);
public:
using SlotTypedTransform = sigc::slot<bool(const T_from&, T_to&)>;
- TransformProp(const SlotTypedTransform& slot) : typed_transform(slot) {}
+ explicit TransformProp(const SlotTypedTransform& slot) : typed_transform(slot) {}
bool operator()(const GValue* from_value, GValue* to_value)
{
_WRAP_METHOD(void reset(), g_checksum_reset)
- //TODO: length should really be gssize, not gsize, when we can break ABI:
-#m4 _CONVERSION(`gsize',`gssize',`(gssize)($3)')
- _WRAP_METHOD(void update(const guchar* data, gsize length), g_checksum_update)
+ _WRAP_METHOD(void update(const guchar* data, gssize length), g_checksum_update)
/** Feeds data into an existing Checksum.
* The checksum must still be open, that is get_string() or get_digest() must not have been called on the checksum.
};
} //namespace Glib
-
G_GNUC_EXTENSION typedef unsigned long long unsigned_long_long;
GLIB_VALUE_BASIC(bool, boolean)
-#ifndef GLIBMM_DISABLE_DEPRECATED
-GLIB_VALUE_BASIC(char, char, -128, 127)
-#endif // GLIBMM_DISABLE_DEPRECATED
GLIB_VALUE_BASIC(signed char, schar, -128, 127)
GLIB_VALUE_BASIC(unsigned char, uchar, 0, 255)
GLIB_VALUE_BASIC(int, int, G_MININT, G_MAXINT)
namespace Glib
{
GLIB_VALUE_BASIC(bool, boolean)
-#ifndef GLIBMM_DISABLE_DEPRECATED
-/// @deprecated Use Value<signed char> instead.
-GLIB_VALUE_BASIC(char, char)
-#endif // GLIBMM_DISABLE_DEPRECATED
/// @newin{2,44}
GLIB_VALUE_BASIC(signed char, int8)
GLIB_VALUE_BASIC(unsigned char, uchar)
return convert_const_gchar_ptr_to_ustring(g_variant_get_string(gobject_, nullptr));
}
-// Variant<Glib::ustring> makes sense for multiple types.
-// See http://library.gnome.org/devel/glib/unstable/glib-GVariant.html#g-variant-get-string
-template <>
-Variant<Glib::ustring>
-VariantBase::cast_dynamic<Variant<Glib::ustring>>(const VariantBase& v) throw(std::bad_cast)
-{
- if (!v.gobj())
- {
- return Variant<Glib::ustring>();
- }
-
- const VariantType vtype = v.get_type();
- if (vtype.equal(VARIANT_TYPE_STRING) || vtype.equal(VARIANT_TYPE_OBJECT_PATH) ||
- vtype.equal(VARIANT_TYPE_SIGNATURE))
- {
- return Variant<Glib::ustring>(const_cast<GVariant*>(v.gobj()), true);
- }
- else
- {
- // std::cerr << "vtype=" << v.get_type_string() << std::endl;
- throw std::bad_cast();
- }
-}
-
/*--------------------Variant<std::string>---------------------*/
Variant<std::string>::Variant() : VariantStringBase()
return result;
}
-// Variant<std::string> makes sense for multiple types.
-// See http://library.gnome.org/devel/glib/unstable/glib-GVariant.html#g-variant-get-string
-template <>
-Variant<std::string>
-VariantBase::cast_dynamic<Variant<std::string>>(const VariantBase& v) throw(std::bad_cast)
-{
- if (!v.gobj())
- {
- return Variant<std::string>();
- }
-
- const VariantType vtype = v.get_type();
- if (vtype.equal(VARIANT_TYPE_STRING) || vtype.equal(VARIANT_TYPE_BYTESTRING) ||
- vtype.equal(VARIANT_TYPE_OBJECT_PATH) || vtype.equal(VARIANT_TYPE_SIGNATURE))
- {
- return Variant<std::string>(const_cast<GVariant*>(v.gobj()), true);
- }
- else
- {
- // std::cerr << "vtype=" << v.get_type_string() << std::endl;
- throw std::bad_cast();
- }
-}
-
std::string
Variant<std::string>::get() const
{
_IGNORE(g_variant_get_string, g_variant_dup_string)
};
-//TODO: When we can break ABI, remove this template specialization.
-template<>
-Variant<Glib::ustring> VariantBase::cast_dynamic< Variant<Glib::ustring> >(const VariantBase& v)
-throw(std::bad_cast);
-
/** Specialization of Variant containing a std::string, for variants of type
* bytestring, string, object path, or signature.
* See also Variant<Glib::ustring> for UTF-8 strings.
_IGNORE(g_variant_get_bytestring, g_variant_dup_bytestring)
};
-//TODO: When we can break ABI, remove this template specialization.
-template<>
-Variant<std::string> VariantBase::cast_dynamic< Variant<std::string> >(const VariantBase& v)
-throw(std::bad_cast);
-
/** Specialization of Variant containing a dictionary entry. See also
* Variant< std::map<K, V> >.
* @newin{2,28}
{
return std::string(g_variant_type_peek_string(gobj()), g_variant_type_get_string_length(gobj()));
}
+
+std::vector<VariantType> VariantType::get_item_types() const
+{
+ std::vector<VariantType> result;
+ auto next_item_type = g_variant_type_first(gobj());
+ while (next_item_type)
+ {
+ result.emplace_back(const_cast<GVariantType*>(next_item_type), true);
+ next_item_type = g_variant_type_next(next_item_type);
+ }
+ return result;
}
+
+} // namespace GLib
_WRAP_METHOD(bool is_subtype_of(const VariantType& supertype) const, g_variant_type_is_subtype_of)
// It's necessary to take an extra reference of the 'const GVariantType*'
-// returned by g_variant_type_element() because it doesn't do that already.
+// returned by g_variant_type_element(), g_variant_type_key() and
+// g_variant_type_value() because they don't do that already.
#m4 _CONVERSION(`const GVariantType*',`VariantType',`Glib::wrap(const_cast<GVariantType*>($3), true)')
_WRAP_METHOD(VariantType element() const, g_variant_type_element)
- _WRAP_METHOD(VariantType first() const, g_variant_type_first)
- _WRAP_METHOD(VariantType next () const, g_variant_type_next)
_WRAP_METHOD(gsize n_items() const, g_variant_type_n_items)
_WRAP_METHOD(VariantType key() const, g_variant_type_key)
_WRAP_METHOD(VariantType value() const, g_variant_type_value)
+ /** Determines the item types of a tuple or dictionary entry type.
+ *
+ * This function may only be used with tuple or dictionary entry types,
+ * but must not be used with the generic tuple type VARIANT_TYPE_TUPLE.
+ *
+ * In the case of a dictionary entry type, returns a vector with
+ * 2 elements, the type of the key followed by the value type.
+ *
+ * An empty vector is returned in case of this %VariantType being VARIANT_TYPE_UNIT.
+ *
+ * @newin{2,52}
+ *
+ * @return The item types of this %VariantType, or an empty vector.
+ */
+ std::vector<VariantType> get_item_types() const;
+ _IGNORE(g_variant_type_first, g_variant_type_next)
+
// This function is part of unexposed API in gvarianttypeinfo.{h,c} for an
// also unexposed GVariantTypeInfo structure of glib.
_IGNORE(g_variant_type_info_get)
class MyObject : public Glib::Object
{
protected:
- MyObject(int id) : m_id(id) {}
+ explicit MyObject(int id) : m_id(id) {}
public:
static Glib::RefPtr<MyObject> create(int id)
}
protected:
- Base64OutputStream(const Glib::RefPtr<Gio::OutputStream>& base_stream)
+ explicit Base64OutputStream(const Glib::RefPtr<Gio::OutputStream>& base_stream)
: Gio::FilterOutputStream(base_stream), column(0), bit_count(0), bit_buffer(0), column_width(72) {}
gssize write_vfunc(const void* buffer, gsize count, const Glib::RefPtr<Gio::Cancellable>& cancellable) override
protected:
using CppClassType = TestInterface_Class;
- TestInterface() : Glib::Interface(derived_interface_class_.init()) {}
+ TestInterface() : Glib::Interface(derived_interface_class_.init()), i_(0) {}
public:
// A real application would never make the constructor public.
// A real application would never make the constructor public.
// It would instead have a protected constructor and a public create() method.
- DerivedObject(int i)
+ explicit DerivedObject(int i)
: Glib::ObjectBase(nullptr),
Glib::Object(Glib::ConstructParams(derived_object_class_.init())),
i_(i)
int
main()
{
- std::list<std::string> alma;
std::string tstring, cstring;
type_nodetree_string* root;
type_nodetree_string* node;
struct WarnCatcher
{
- WarnCatcher(const std::string& domain)
+ explicit WarnCatcher(const std::string& domain)
: m_domain(domain), m_old_flags(g_log_set_fatal_mask(m_domain.c_str(), get_log_flags()))
{
}