Imported Upstream version 2.51.5 upstream/2.51.5
authorDongHun Kwak <dh0128.kwak@samsung.com>
Mon, 7 Sep 2020 07:18:32 +0000 (00:18 -0700)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Mon, 7 Sep 2020 07:18:32 +0000 (00:18 -0700)
NEWS
configure.ac
gio/giomm.h
gio/src/application.hg
gio/src/filelist.am
gio/src/propertyaction.ccg [new file with mode: 0644]
gio/src/propertyaction.hg [new file with mode: 0644]
glib/glibmm/utility.h
glib/src/variant.hg
tests/glibmm_variant/main.cc

diff --git a/NEWS b/NEWS
index 672b214..cb86808 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,19 @@
+2.51.5
+
+Gio:
+* Application: get_default(): Correct the reference counting.
+  (KJell Ahlstedt) Bug #779936 (James Legg)
+* Add PropertyAction.
+  (Kjell Ahlstedt)
+
+Glib:
+* Remove Glib::unconst() because it is unused and unnecessary.
+  (Kjell Ahlstedt)
+* Variant: Add template specialization for std::tuple,
+  and a test.
+  (Alexander Rössler, Kjell Ahlstedt) Bug #777791
+
+
 2.51.2 (unstable):
 Distro packagers should probably not package this yet.
 
index 6167baf..32353dc 100644 (file)
@@ -15,7 +15,7 @@
 ## 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.2],
+AC_INIT([glibmm], [2.51.5],
         [http://bugzilla.gnome.org/enter_bug.cgi?product=glibmm],
         [glibmm], [http://www.gtkmm.org/])
 AC_PREREQ([2.59])
index a7c0a91..8d5376b 100644 (file)
 #include <giomm/permission.h>
 #include <giomm/pollableinputstream.h>
 #include <giomm/pollableoutputstream.h>
+#include <giomm/propertyaction.h>
 #include <giomm/proxy.h>
 #include <giomm/proxyaddress.h>
 #include <giomm/proxyresolver.h>
index e4d3a63..6b36ad3 100644 (file)
@@ -344,7 +344,7 @@ public:
   /// Unsets any existing default application.
   static void unset_default();
 
-  _WRAP_METHOD(static Glib::RefPtr<Application> get_default(), g_application_get_default)
+  _WRAP_METHOD(static Glib::RefPtr<Application> get_default(), g_application_get_default, refreturn)
 
   _WRAP_METHOD(void mark_busy(), g_application_mark_busy)
   _WRAP_METHOD(void unmark_busy(), g_application_unmark_busy)
index 0095128..ca5a3ac 100644 (file)
@@ -94,6 +94,7 @@ giomm_files_any_hg =                  \
        permission.hg           \
        pollableinputstream.hg          \
        pollableoutputstream.hg         \
+       propertyaction.hg \
        proxy.hg                        \
        proxyaddress.hg                 \
        proxyresolver.hg                \
diff --git a/gio/src/propertyaction.ccg b/gio/src/propertyaction.ccg
new file mode 100644 (file)
index 0000000..85da4a8
--- /dev/null
@@ -0,0 +1,31 @@
+/* Copyright (C) 2017 The giomm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * 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/>.
+ */
+
+#include <gio/gio.h>
+
+namespace Gio
+{
+
+PropertyAction::PropertyAction(const Glib::ustring& name,
+  const Glib::PropertyProxy_Base& property_proxy, bool invert_boolean)
+:
+_CONSTRUCT("name", name.c_str(), "object", property_proxy.get_object()->gobj(),
+           "property-name",  property_proxy.get_name(),
+           "invert-boolean", invert_boolean)
+{
+}
+
+} // namespace Gio
diff --git a/gio/src/propertyaction.hg b/gio/src/propertyaction.hg
new file mode 100644 (file)
index 0000000..5037146
--- /dev/null
@@ -0,0 +1,121 @@
+/* Copyright (C) 2017 The giomm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * 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/>.
+ */
+
+#include <glibmm/object.h>
+#include <glibmm/refptr.h>
+#include <giomm/action.h>
+
+_DEFS(giomm,gio)
+_PINCLUDE(glibmm/private/object_p.h)
+
+namespace Gio
+{
+/** An Action reflecting a Glib::Object property.
+ *
+ * A %PropertyAction is a way to get an Action with a state value
+ * reflecting and controlling the value of a Glib::Object property.
+ *
+ * The state of the action will correspond to the value of the property.
+ * Changing it will change the property (assuming the requested value
+ * matches the requirements as specified in the GParamSpec, used when the
+ * property was installed).
+ *
+ * Only the most common types are presently supported. Booleans are
+ * mapped to booleans, strings to strings, signed/unsigned integers to
+ * int32/uint32 and floats and doubles to doubles.
+ *
+ * If the property is an enum then the state will be string-typed and
+ * conversion will automatically be performed between the enum value and
+ * "nick" string as per the GEnumValue table.
+ *
+ * Flags types are not currently supported.
+ *
+ * Properties of object types, boxed types and pointer types are not
+ * supported and probably never will be.
+ *
+ * Properties of Glib::Variant types are not currently supported.
+ *
+ * If the property is boolean-valued then the action will have a nullptr
+ * parameter type, and activating the action (with no parameter) will
+ * toggle the value of the property.
+ *
+ * In all other cases, the parameter type will correspond to the type of
+ * the property.
+ *
+ * The general idea here is to reduce the number of locations where a
+ * particular piece of state is kept (and therefore has to be synchronised
+ * between). %PropertyAction does not have a separate state that is kept
+ * in sync with the property value -- its state is the property value.
+ *
+ * For example, it might be useful to create an Action corresponding to
+ * property_visible_child_name() of a Gtk::Stack so that the current
+ * page can be switched from a menu. The active radio indication in the
+ * menu is then directly determined from the active page of the Gtk::Stack.
+ *
+ * An anti-example would be binding property_active_id() on a Gtk::ComboBox.
+ * This is because the state of the combobox itself is probably uninteresting
+ * and is actually being used to control something else.
+ *
+ * Another anti-example would be to bind to property_visible_child_name()
+ * of a Gtk::Stack if this value is actually stored in Gio::Settings.
+ * In that case, the real source of the value is
+ * Gio::Settings. If you want an Action to control a setting stored in
+ * Gio::Settings, see Gio::Settings::create_action() instead, and possibly
+ * combine its use with Gio::Settings::bind().
+ *
+ * @newin{2,52}
+ */
+class PropertyAction : public Glib::Object, public Action
+{
+  _CLASS_GOBJECT(PropertyAction, GPropertyAction, G_PROPERTY_ACTION, Glib::Object, GObject)
+  _IMPLEMENTS_INTERFACE(Action)
+
+protected:
+  PropertyAction(const Glib::ustring& name, const Glib::PropertyProxy_Base& property_proxy,
+    bool invert_boolean = false);
+
+public:
+  /** Creates an Action corresponding to the value of property @a property_proxy.
+   *
+   * The property must be existent and readable and writable (and not construct-only).
+   *
+   * This function takes a reference on the property's object and doesn't
+   * release it until the action is destroyed.
+   *
+   * @param name The name of the action to create.
+   * @param property_proxy The property to bind.
+   * @param invert_boolean If <tt>true</tt>, the state of the action will be
+   *        the negation of the property value, provided the property is boolean.
+   * @return A new %PropertyAction.
+   *
+   * @newin{2,52}
+   */
+  _WRAP_CREATE(const Glib::ustring& name, const Glib::PropertyProxy_Base& property_proxy,
+    bool invert_boolean = false)
+
+  _WRAP_PROPERTY("name", Glib::ustring, newin "2,52")
+  _WRAP_PROPERTY("parameter-type", Glib::VariantType, newin "2,52")
+  _WRAP_PROPERTY("enabled", bool, newin "2,52")
+  _WRAP_PROPERTY("state-type", Glib::VariantType, newin "2,52")
+  _WRAP_PROPERTY("state", Glib::VariantBase, newin "2,52")
+  //_WRAP_PROPERTY("object", Glib::ObjectBase) // write-only, construct-only
+  //_WRAP_PROPERTY("property-name", Glib::ustring) // write-only, construct-only
+  _WRAP_PROPERTY("invert-boolean", bool, newin "2,52")
+
+  // There are no methods (apart from ctor and create), signals or vfuncs.
+};
+
+} // namespace Gio
index 3cbca14..5e17183 100644 (file)
@@ -42,17 +42,6 @@ make_unique_ptr_gfree(T* p)
   return std::unique_ptr<T[], decltype(&g_free)>(p, &g_free);
 }
 
-// TODO: Deprecate this? We don't use it ourselves.
-/** Removes the const nature of a ptr
- *
- */
-template <class T>
-inline T*
-unconst(const T* t)
-{
-  return const_cast<T*>(t);
-}
-
 // Convert const gchar* to ustring, while treating NULL as empty string.
 inline Glib::ustring
 convert_const_gchar_ptr_to_ustring(const char* str)
index 92e0b6b..4843398 100644 (file)
@@ -26,6 +26,7 @@ _DEFS(glibmm,glib)
 #include <utility>
 #include <vector>
 #include <map>
+#include <tuple>
 #include <stdexcept>
 #include <typeinfo>
 
@@ -944,6 +945,71 @@ public:
   VariantIter get_iter() const;
 };
 
+/** Specialization of Variant containing a tuple.
+ * @newin{2,52}
+ * @ingroup Variant
+ */
+template <class... Types>
+class Variant<std::tuple<Types...>> : public VariantContainerBase
+{
+public:
+  using CppContainerType = std::tuple<Types...>;
+
+  /// Default constructor
+  Variant<std::tuple<Types...>>()
+  : VariantContainerBase()
+  {}
+
+  /** GVariant constructor.
+   * @param castitem The GVariant to wrap.
+   * @param take_a_reference Whether to take an extra reference of the GVariant
+   *        or not (not taking one could destroy the GVariant with the wrapper).
+   */
+  explicit Variant<std::tuple<Types...>>(GVariant* castitem, bool take_a_reference = false)
+  : VariantContainerBase(castitem, take_a_reference)
+  {}
+
+  /** Creates a new Variant containing a tuple.
+   * @param data The tuple to use for creation.
+   * @return The new Variant holding a tuple.
+   * @newin{2,52}
+   */
+  static Variant<std::tuple<Types...>> create(const std::tuple<Types...>& data);
+
+  /** Gets the VariantType.
+   * @return The VariantType.
+   * @newin{2,52}
+   */
+  static const VariantType& variant_type() G_GNUC_CONST;
+
+  /** Gets a specific element from the tuple.
+   * It is an error if @a index is greater than or equal to the number of
+   * elements in the tuple. See VariantContainerBase::get_n_children().
+   *
+   * @param index The index of the element.
+   * @return The tuple element at index @a index.
+   * @throw std::out_of_range
+   * @newin{2,52}
+   */
+  template<class T>
+  T get_child(gsize index) const;
+
+  template<class T>
+  Variant<T> get_child_variant(gsize index) const;
+
+  /** Gets the tuple of the Variant.
+   * @return The tuple.
+   * @newin{2,52}
+   */
+  std::tuple<Types...> get() const;
+
+  /** Gets a VariantIter of the Variant.
+   * @return The VariantIter.
+   * @newin{2,52}
+   */
+  VariantIter get_iter() const;
+};
+
 } // namespace Glib
 
 
@@ -1229,4 +1295,124 @@ VariantIter Variant< std::map<K, V> >::get_iter() const
   return VariantContainerBase::get_iter(variant_type());
 }
 
+/*---------------------Variant<std::tuple<class... Types>> --------------------*/
+
+// static
+template <class... Types>
+const VariantType& Variant<std::tuple<Types...>>::variant_type()
+{
+  std::vector<VariantType> types;
+  auto expander = [&types](const VariantType &type) mutable -> int
+  {
+    types.push_back(type);
+    return 0;
+  };
+
+  // expands the variadic template parameters
+  using swallow = int[]; // ensures left to right order
+  swallow{(expander(Variant<Types>::variant_type()))...};
+  static auto type = VariantType::create_tuple(types);
+
+  return type;
+}
+
+namespace detail
+{
+template <class Tuple, std::size_t... Is>
+void expand_tuple(std::vector<VariantBase> &variants, const Tuple & t,
+                  std::index_sequence<Is...>)
+{
+  using swallow = int[]; // ensures left to right order
+  auto expander = [&variants](const VariantBase &variant) -> int
+  {
+    variants.push_back(variant);
+    return 0;
+  };
+  (void)swallow {(expander(Variant<typename std::tuple_element<Is, Tuple>::type>::create(std::get<Is>(t))))...};
+}
+} // namespace detail
+
+template <class... Types>
+Variant<std::tuple<Types...>>
+Variant<std::tuple<Types...>>::create(const std::tuple<Types...>& data)
+{
+  // create a vector containing all tuple values as variants
+  std::vector<Glib::VariantBase> variants;
+  detail::expand_tuple(variants, data, std::index_sequence_for<Types...>{});
+
+  using var_ptr = GVariant*;
+  var_ptr* const var_array = new var_ptr[sizeof... (Types)];
+
+  for (std::vector<VariantBase>::size_type i = 0; i < variants.size(); i++)
+    var_array[i] = const_cast<GVariant*>(variants[i].gobj());
+
+  Variant<std::tuple<Types...>> result = Variant<std::tuple<Types...>>(
+          g_variant_new_tuple(var_array, variants.size()));
+
+  return result;
+}
+
+template <class... Types>
+template <class T>
+T Variant<std::tuple<Types...>>::get_child(gsize index) const
+{
+  Variant<T> entry;
+  VariantContainerBase::get_child(entry, index);
+  return entry.get();
+}
+
+template <class... Types>
+template <class T>
+Variant<T> Variant<std::tuple<Types...>>::get_child_variant(gsize index) const
+{
+  Variant<T> entry;
+  VariantContainerBase::get_child(entry, index);
+  return entry;
+}
+
+namespace detail
+{
+// swallows any argument
+template <class T>
+constexpr int any_arg(T&& arg)
+{
+  (void)arg;
+  return 0;
+}
+
+template <class Tuple, std::size_t... Is>
+void assign_tuple(std::vector<VariantBase> &variants, Tuple & t, std::index_sequence<Is...>)
+{
+  int i = 0;
+  using swallow = int[]; // ensures left to right order
+  (void)swallow {(any_arg(std::get<Is>(t) = VariantBase::cast_dynamic<Variant<typename std::tuple_element<Is, Tuple>::type > >(variants[i++]).get()))...};
+}
+} // namespace detail
+
+template <class... Types>
+std::tuple<Types...> Variant<std::tuple<Types...>>::get() const
+{
+  std::tuple<Types...> data;
+  int i = 0;
+
+  std::vector<VariantBase> variants;
+  using swallow = int[]; // ensures left to right order
+  auto expander = [&variants, &i](const VariantBase &variant) -> int
+  {
+    variants.push_back(variant);
+    return i++;
+  };
+  swallow{(expander(get_child_variant<Types>(i)))...};
+  detail::assign_tuple(variants, data, std::index_sequence_for<Types...>{});
+
+  return data;
+}
+
+template< class... Types>
+VariantIter Variant<std::tuple<Types...>>::get_iter() const
+{
+  const auto type = variant_type();
+  return VariantContainerBase::get_iter(type);
+}
+
 } // namespace Glib
index dca4ee3..4d3c2c7 100644 (file)
@@ -11,6 +11,70 @@ std::ostream& ostr = debug;
 static void test_variant_floating();
 static void test_dynamic_cast();
 
+namespace
+{
+
+int test_tuple()
+{
+  using TupleType = std::tuple<guint16, Glib::ustring, bool>;
+  using MapType = std::map<guint16, TupleType>;
+  bool result_ok = true;
+
+  // First tuple
+  const guint16 q1 = 2;
+  const Glib::ustring s1 = "Hi there";
+  const bool b1 = false;
+  auto t1 = std::make_tuple(q1, s1, b1);
+  auto tuple1_variant = Glib::Variant<TupleType>::create(t1);
+
+  // Second tuple
+  const guint16 q2 = 3;
+  const Glib::ustring s2 = "Hello";
+  const bool b2 = true;
+  auto t2 = std::make_tuple(q2, s2, b2);
+  auto tuple2_variant = Glib::Variant<TupleType>::create(t2);
+
+  // Insert the tuples in a map.
+  MapType m;
+  m[4] = t1;
+  m[5] = t2;
+  auto map_variant = Glib::Variant<MapType>::create(m);
+
+  std::string type_string = tuple1_variant.variant_type().get_string();
+  ostr << "Type string of tuple1: " << type_string << std::endl;
+  result_ok &= type_string == "(qsb)";
+
+  type_string = tuple2_variant.get_type_string();
+  ostr << "Type string of tuple2: " << type_string << std::endl;
+  result_ok &= type_string == "(qsb)";
+
+  type_string = map_variant.variant_type().get_string();
+  ostr << "Type string of map of tuples: " << type_string << std::endl;
+  result_ok &= map_variant.get_type_string() == "a{q(qsb)}";
+
+  // Extract from the map of tuples.
+  std::pair<guint16, TupleType> child0 = map_variant.get_child(0);
+  ostr << "Index of first map entry: " << child0.first << std::endl;
+  result_ok &= child0.first == 4;
+  auto extracted_tuple = child0.second;
+  auto q3 = std::get<guint16>(extracted_tuple);
+  auto s3 = std::get<Glib::ustring>(extracted_tuple);
+  auto b3 = std::get<bool>(extracted_tuple);
+  ostr << "Extracted tuple1 from map: (" << q3 << ", " << s3 << ", " << b3 << ")" << std::endl;
+  result_ok &= q3 == q1 && s3 == s1 && b3 == b1;
+
+  // Extract from a tuple.
+  auto q4 = tuple2_variant.get_child<guint16>(0);
+  auto s4 = tuple2_variant.get_child_variant<Glib::ustring>(1).get();
+  auto b4 = std::get<bool>(tuple2_variant.get());
+  ostr << "Extracted tuple2: (" << q4 << ", " << s4 << ", " << b4 << ")" << std::endl;
+  result_ok &= q4 == q2 && s4 == s2 && b4 == b2;
+
+  return result_ok ? EXIT_SUCCESS : EXIT_FAILURE;
+}
+
+} // anonymous namespace
+
 int
 main(int, char**)
 {
@@ -163,7 +227,7 @@ main(int, char**)
   test_variant_floating();
   test_dynamic_cast();
 
-  return EXIT_SUCCESS;
+  return test_tuple();
 }
 
 // Test casting of multiple types to a ustring: