Repository: gtk-rs/gtk3-rs (language: rust)

Issue:
TreeViewColumn::new_with_attributes
If your following the [GTK3 TreeView documentation](https://developer.gnome.org/gtk3/stable/TreeWidget.html) then gtk_tree_view_column_new_with_attributes is used.

Its a bit of a stumbling block for those new to GTK to figure out the order of pack_start and add_attribute.


Discussion / hints:
That function is a bit hard to bind. From what I can see it would have to be re-implemented around the existing bound API, or instead of that you'd use the [TreeViewColumnBuilder](https://gtk-rs.org/docs/gtk/struct.TreeViewColumnBuilder.html) (but that doesn't include the cell renderer so `pack_start()` would still be necessary AFAIU).
It can be copied from https://github.com/gtk-rs/gtk4-rs/blob/master/gtk4/src/tree_view_column.rs#L10 

Fix patch:
diff --git a/gtk/Gir.toml b/gtk/Gir.toml
index 72ef550a39e6..4da9cc8cc1fa 100644
--- a/gtk/Gir.toml
+++ b/gtk/Gir.toml
@@ -2646,6 +2646,10 @@ generate_builder = true
         [[object.function.parameter]]
         name = "iter"
         const = true
+    [[object.function]]
+    name = "new_with_attributes"
+    manual = true # va_args
+    rename = "with_attributes"
 
 [[object]]
 name = "Gtk.Viewport"
diff --git a/gtk/src/auto/tree_view_column.rs b/gtk/src/auto/tree_view_column.rs
index c042efaee988..fc5c9d3b3775 100644
--- a/gtk/src/auto/tree_view_column.rs
+++ b/gtk/src/auto/tree_view_column.rs
@@ -50,12 +50,6 @@ impl TreeViewColumn {
         }
     }
 
-    //#[doc(alias = "gtk_tree_view_column_new_with_attributes")]
-    //#[doc(alias = "new_with_attributes")]
-    //pub fn with_attributes(title: &str, cell: &impl IsA<CellRenderer>, : /*Unknown conversion*//*Unimplemented*/Fundamental: VarArgs) -> TreeViewColumn {
-    //    unsafe { TODO: call ffi:gtk_tree_view_column_new_with_attributes() }
-    //}
-
     // rustdoc-stripper-ignore-next
     /// Creates a new builder-pattern struct instance to construct [`TreeViewColumn`] objects.
     ///
diff --git a/gtk/src/lib.rs b/gtk/src/lib.rs
index b289f6ca4681..7299ae813f6d 100644
--- a/gtk/src/lib.rs
+++ b/gtk/src/lib.rs
@@ -115,6 +115,7 @@ mod tree_path;
 mod tree_row_reference;
 mod tree_sortable;
 mod tree_store;
+mod tree_view_column;
 mod widget;
 
 #[macro_use]
diff --git a/gtk/src/tree_view_column.rs b/gtk/src/tree_view_column.rs
new file mode 100644
index 000000000000..b0cea2baaa78
--- /dev/null
+++ b/gtk/src/tree_view_column.rs
@@ -0,0 +1,90 @@
+// Take a look at the license at the top of the repository in the LICENSE file.
+
+use crate::{prelude::TreeViewColumnExt, CellRenderer, TreeViewColumn};
+use glib::object::IsA;
+use glib::translate::*;
+
+impl TreeViewColumn {
+    #[doc(alias = "gtk_tree_view_column_new_with_attributes")]
+    pub fn with_attributes(
+        title: &str,
+        cell_renderer: &impl IsA<CellRenderer>,
+        attributes: &[(&str, i32)],
+    ) -> Self {
+        assert_initialized_main_thread!();
+        let tree_view_column = TreeViewColumn::new();
+        tree_view_column.set_title(title);
+        tree_view_column.pack_start(cell_renderer, true);
+        tree_view_column.set_attributes(cell_renderer, attributes);
+
+        tree_view_column
+    }
+
+    #[doc(alias = "gtk_tree_view_column_add_attribute")]
+    pub fn add_attribute(
+        &self,
+        cell_renderer: &impl IsA<CellRenderer>,
+        attribute: &str,
+        column: i32,
+    ) {
+        unsafe {
+            ffi::gtk_tree_view_column_add_attribute(
+                self.to_glib_none().0,
+                cell_renderer.as_ref().to_glib_none().0,
+                attribute.to_glib_none().0,
+                column,
+            )
+        }
+    }
+
+    #[doc(alias = "gtk_tree_view_column_set_attributes")]
+    pub fn set_attributes(
+        &self,
+        cell_renderer: &impl IsA<CellRenderer>,
+        attributes: &[(&str, i32)],
+    ) {
+        self.clear_attributes(cell_renderer);
+        attributes.iter().for_each(|(attribute, column)| {
+            self.add_attribute(cell_renderer, attribute, *column);
+        });
+    }
+
+    #[doc(alias = "gtk_tree_view_column_clear_attributes")]
+    pub fn clear_attributes(&self, cell_renderer: &impl IsA<CellRenderer>) {
+        unsafe {
+            ffi::gtk_tree_view_column_clear_attributes(
+                self.to_glib_none().0,
+                cell_renderer.as_ref().to_glib_none().0,
+            );
+        }
+    }
+
+    #[doc(alias = "gtk_tree_view_column_pack_end")]
+    pub fn pack_end(&self, cell_renderer: &impl IsA<CellRenderer>, expand: bool) {
+        unsafe {
+            ffi::gtk_tree_view_column_pack_end(
+                self.to_glib_none().0,
+                cell_renderer.as_ref().to_glib_none().0,
+                expand.into_glib(),
+            )
+        }
+    }
+
+    #[doc(alias = "gtk_tree_view_column_pack_start")]
+    pub fn pack_start(&self, cell_renderer: &impl IsA<CellRenderer>, expand: bool) {
+        unsafe {
+            ffi::gtk_tree_view_column_pack_start(
+                self.to_glib_none().0,
+                cell_renderer.as_ref().to_glib_none().0,
+                expand.into_glib(),
+            )
+        }
+    }
+
+    #[doc(alias = "gtk_tree_view_column_clear")]
+    pub fn clear(&self) {
+        unsafe {
+            ffi::gtk_tree_view_column_clear(self.to_glib_none().0);
+        }
+    }
+}


Test patch: