How to select item in ColumnView

I have a short example:

import gi

gi.require_version("Adw", "1")
gi.require_version("Gtk", "4.0")

from gi.repository import Adw, Gio, GObject, Gtk  # noqa

class Value(GObject.Object):
    __gtype_name__ = 'Value'

    def __init__(self, Value_name):
        super().__init__()
        self._Value_name = Value_name

    @GObject.Property(type=str)
    def Value_name(self):
        return self._Value_name

    def __repr__(self):
        return f"Value(Value_name={self.Value_name})"  # noqa


class ExampleWindow(Gtk.ApplicationWindow):
    def __init__(self, app):
        super().__init__(application=app, title="ColumnView_Values", default_width=300)
        self.connect('show', self.visibile_window)
        
        # Model
        self.model = Gio.ListStore(item_type=Value)
        for entry in range(1, 200):
            self.model.append(Value(Value_name=entry))

        # Factory
        factory = Gtk.SignalListItemFactory()
        factory.connect("setup", self._on_factory_setup)
        factory.connect("bind", self._on_factory_bind, "Value_name")
        factory.connect("unbind", self._on_factory_unbind, "Value_name")
        factory.connect("teardown", self._on_factory_teardown)
        
        # SingleSelection
        self.cv_selected = Gtk.SingleSelection(model=self.model)
        self.cv_selected.connect("selection-changed", self._on_selection_change)
        self.cv_selected.set_autoselect(True)
        self.cv_selected.set_can_unselect(False)
        
        # View
        self.cv = Gtk.ColumnView(model=self.cv_selected)
        self.cv.connect("activate", self._on_activate_cv)
        self.cv.set_property('vexpand', True)
        self.cv.set_single_click_activate(False)
        
        # Column
        col1 = Gtk.ColumnViewColumn(title="Value", factory=factory)
        col1.props.expand = True
        self.cv.append_column(col1)

        # ScrolledWindow
        self.scrollable_window = Gtk.ScrolledWindow()
        self.scrollable_window.set_child(self.cv)
        self.scrollable_window.set_has_frame(True)
        self.scrollable_window.set_max_content_width(300)
        self.scrollable_window.set_min_content_width(200)
        self.scrollable_window.set_max_content_height(1000)
        self.scrollable_window.set_min_content_height(700)
        self.scrollable_window.set_overlay_scrolling(False)
        self.adj_v = Gtk.Adjustment.new(value=0.0, lower=0.0, upper=(self.model.get_n_items() * 35), step_increment=(self.scrollable_window.get_min_content_height() - 30) / 10, page_increment=603.0, page_size=(self.scrollable_window.get_min_content_height() - 30))
        self.adj_v = self.scrollable_window.set_vadjustment(self.adj_v)
        
        # Button
        self.button = Gtk.Button(label='Update')
        self.button.connect('clicked', self._onclicked_button)
        
        # Box
        box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=12)
        box.append(self.button)
        box.append(self.scrollable_window)
        
        # Window
        self.set_child(box)
        
    def visibile_window(self, widget):
        print('---visibile_window---')
        print('Select item 4')
        self.cv_selected.set_selected(3)
        self.cv_selected.select_item(4, True)
        self.cv_selected.select_item(5, True)
        self.cv_selected.set_selected(6)
        
    def _onclicked_button(self, button):
        print('---_onclicked_button---')
        print('Select item 33')
        self.cv_selected.set_selected(32)
        
    def _on_selection_change(self, selection_model, position, n_items):
        print('---_on_selection_change---')
        item_selected = self.cv_selected.get_selected()
        item_all = self.model.get_n_items()
        print('Element %s from %s selected' % (item_selected, item_all))
        
        # Values
        self.adj_v = self.scrollable_window.get_vadjustment()
        item_all_upper = self.adj_v.get_upper() - self.adj_v.get_page_size()
        item_step = self.adj_v.get_step_increment()
        item_page_size = self.adj_v.get_page_size()
        
        # Take widget-size to define the factor
        item_visible = round(self.adj_v.get_page_size() / 35)
        item_visible_factor = round(item_visible / 2 - 1)
        
        # Calculate the scroll-value
        if item_selected < item_visible_factor:
            item_selected_value = 0
        elif item_selected > item_all - item_visible_factor:
            item_selected_value = item_all_upper
        else:
            item_selected_value = (item_selected - item_visible_factor) * 35
            
        # Set the scroll value
        self.adj_v.set_value(item_selected_value)
        
    def _on_activate_cv(self, position, user_data):
        print('_on_activate_cv')
        print(f'Selected = {self.model.get_item(user_data).Value_name}')
        
    def _on_factory_setup(self, factory, list_item):
        cell = Gtk.Inscription()
        cell._binding = None
        list_item.set_child(cell)

    def _on_factory_bind(self, factory, list_item, what):
        cell = list_item.get_child()
        Value = list_item.get_item()
        cell._binding = Value.bind_property(what, cell, "text", GObject.BindingFlags.SYNC_CREATE)

    def _on_factory_unbind(self, factory, list_item, what):
        cell = list_item.get_child()
        if cell._binding:
            cell._binding.unbind()
            cell._binding = None

    def _on_factory_teardown(self, factory, list_item):
        cell = list_item.get_child()
        cell._binding = None

    def _on_factory_teardown(self, factory, list_item):
        cell = list_item.get_child()
        cell._binding = None

class ExampleApp(Adw.Application):
    def __init__(self):
        super().__init__()
        self.window = None

    def do_activate(self):
        if self.window is None:
            self.window = ExampleWindow(self)
        self.window.present()

app = ExampleApp()
app.run([])

When I start, the 7 will be selected. But when I use the arrow-up or arrow-down key to change the selection, it’s start with 1.

What should I have to do, to make the start with the selected value 7 and not with 1?

The column view keeps the selection state as part of the model (the selection model). You can use the GtkSelectionModel api to change the selection

Thanks for the quick answer.

In my example I use:

        self.cv_selected.select_item(5, True)
        self.cv_selected.set_selected(6)

First line use Gtk.SelectionModel method = Gtk.SelectionModel - Interfaces - Gtk 4.0

Second line use Gtk.SingleSelection method = Gtk.SingleSelection - Classes - Gtk 4.0

The 7 is selected and I think it is OK.
My problem is, when I use the arrow-up or arrow-down keys, the selection 7 is not used. It’s starting with 1.

For me it seems that the selection model differs between mouse-selection and keyboard-selection. How can I let the keyboard-selection start at the 7 too?

If nothing beter i will explor this cursor way.

Thanks for the answer, but I try to migrate from TreeView to ColumnView, cause someone has the idea to set TreeView to the state of “deprecated”… :roll_eyes:

Because that’s not handled by the selection: it’s handled by key focus.

You need to grab the focus on the widget inside the row.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.