ColumnView, ListStore item changes

Hi,

I am using a Gtk.ColumnView with a Gio.ListStore and a Gtk.SingleSelection.

When I modify Item properties on a specific event, the changes are not visible in the ColumnView. If I select another ListItem in the ColumnView, then the values are updated.

How should I proceed so that the ListItem is refreshed each time some of the Item properties are changed ?

Kind regards,
Vincent

Maybe calling the signal GListStore.items_changed is the right way to implement it.

Not really, that is for them the items are added/removed from the model

It sounds like @vcottineau is interested in changes to an item - in which case signals on that item are the solution

Hi @zbrown,

Can you give me more details on which and how to call this event ?

Regards,
Vincent

I have no idea what your object is or what signals it has :slight_smile:

Ok sorry, I thought it’s some kind of native feature. I am using an object called Item inherited from GObject which is used to populate a Gio.Listore. There is a Button in my ColumnView and when it’s clicked the signal on_button_refresh_clicked is triggered.

Below is the full code extract:

from gi.repository import Gio, Gtk, GObject, Pango


from pygpxviewer.app_window_details import AppWindowDetails
from pygpxviewer.helpers import sqlite_helper, gpx_helper


class Item(GObject.GObject):
    __gtype_name__ = "item"

    path = GObject.Property(type=str)
    points = GObject.Property(type=int)
    length = GObject.Property(type=float)
    up_hill = GObject.Property(type=float)
    down_hill = GObject.Property(type=float)

    def __init__(self, path, points, length, up_hill, down_hill):
        super().__init__()

        self.path = path
        self.points = points
        self.length = length
        self.up_hill = up_hill
        self.down_hill = down_hill


# @Gtk.Template(resource_path="/com/github/pygpxviewer/ui/app_column_view.ui")
class AppColumnView(Gtk.ColumnView):
    __gtype_name__ = "app_column_view"

    sort_list_model = Gtk.Template.Child()

    def __init__(self,):
        super().__init__()

        self.folder_path = None
        self.search_entry_value = None

        self.set_show_row_separators(True)
        self.set_show_column_separators(True)

        self.single_selection = Gtk.SingleSelection()
        self.sort_list_model = Gtk.SortListModel()
        self.list_store = Gio.ListStore()

        self.set_model(self.single_selection)
        self.single_selection.set_model(self.sort_list_model)
        self.sort_list_model.set_model(self.list_store)
        self.sort_list_model.set_sorter(self.get_sorter())

        columns = [
            {"title": "Path", "property": "path", "expand": True, "setup": self.factory_setup_label, "bind": self.factory_bind_label},
            {"title": "Points (nb)", "property": "points", "expand":  False, "setup": self.factory_setup_label, "bind": self.factory_bind_label},
            {"title": "Length (km)", "property": "length", "expand":  False, "setup": self.factory_setup_label, "bind": self.factory_bind_label},
            {"title": "UpHill (m)", "property": "up_hill", "expand":  False, "setup": self.factory_setup_label, "bind": self.factory_bind_label},
            {"title": "DownHill (m)", "property": "down_hill", "expand":  False, "setup": self.factory_setup_label, "bind": self.factory_bind_label},
            {"title": "Actions", "property": None, "expand":  False, "setup": self.factory_setup_actions, "bind": None}
        ]

        for column in columns:
            column_view_column = Gtk.ColumnViewColumn()
            column_view_column.set_title(column["title"])
            column_view_column.set_expand(column["expand"])

            signal_list_item_factory = Gtk.SignalListItemFactory()
            signal_list_item_factory.connect("setup", column["setup"])

            if column["bind"]:
                signal_list_item_factory.connect("bind", column["bind"], column["property"])

                # property_expression = Gtk.PropertyExpression.new(Item, None, column["property"])
                # string_sorter = Gtk.StringSorter()
                # string_sorter.set_expression(property_expression)
                # column.set_sorter(string_sorter)

            column_view_column.set_factory(signal_list_item_factory)
            self.append_column(column_view_column)

        self.reset_liststore()

    def reset_liststore(self):
        self.list_store.remove_all()
        records = sqlite_helper.get_records()
        for record in records:
            _, path, points, length, up_hill, down_hill = record
            item =  Item(path, points, length, up_hill, down_hill)
            if self.search_entry_value:
                if self.search_entry_value in path.lower():
                    self.list_store.append(item)
            else:
                self.list_store.append(item)

    def on_folder_path_changed(self, app_window, g_param_spec):
        self.folder_path = app_window.get_property(g_param_spec.name)

    def on_search_entry_changed(self, editable):
        self.search_entry_value = editable.get_text().lower()
        self.reset_liststore()

    def factory_setup_label(self, factory, list_item):
        label = Gtk.Label()
        label.set_ellipsize(Pango.EllipsizeMode.END)
        label.set_halign(Gtk.Align.START)
        list_item.set_child(label)

    def factory_setup_actions(self, factory, list_item):
        box = Gtk.Box(spacing=6)

        button_view = Gtk.Button.new_from_icon_name("mark-location-symbolic")
        button_refresh = Gtk.Button.new_from_icon_name("view-refresh-symbolic")

        context = button_view.get_style_context()
        Gtk.StyleContext.add_class(context, "column_view_button")

        context = button_refresh.get_style_context()
        Gtk.StyleContext.add_class(context, "column_view_button")

        button_view.connect("clicked", self.on_button_view_clicked, list_item)
        button_refresh.connect("clicked", self.on_button_refresh_clicked, list_item)

        box.append(button_view)
        box.append(button_refresh)

        list_item.set_child(box)

    def factory_bind_label(self, factory, list_item, property):
        label = list_item.get_child()
        data = list_item.get_item()
        if property == "path":
            label.set_text(data.get_property(property).replace(self.folder_path, ""))
        else:
            label.set_text(str(round(data.get_property(property))))

    def on_button_view_clicked(self, button, list_item):
        position = list_item.get_position()
        self.single_selection.set_selected(position)
        selected_item = self.single_selection.get_selected_item()
        app_window_details = AppWindowDetails(selected_item.path)
        app_window_details.show()

    def on_button_refresh_clicked(self, button, list_item):
        position = list_item.get_position()
        self.single_selection.set_selected(position)
        selected_item = self.single_selection.get_selected_item()

        gpx_helper.set_gpx(selected_item.path)
        gpx_helper.set_gpx_info()

        path = str(selected_item.path)
        points = gpx_helper.get_gpx_points_nb()
        length = gpx_helper.get_gpx_length()
        up_hill = gpx_helper.get_gpx_up_hill()
        down_hill = gpx_helper.get_gpx_down_hill()

        record = (path, points, length, up_hill, down_hill)
        sqlite_helper.update_record(record)

        selected_item.path = path
        selected_item.points = points
        selected_item.length = length
        selected_item.up_hill = up_hill
        selected_item.down_hill = down_hill

Kind regards,
Vincent

Hi @zbrown,

If you can have a look at my previous answer.

Regards,
Vincent

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