{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n# GTK4 spreadsheet\n\nExample of embedding Matplotlib in an application and interacting with a\ntreeview to store data.  Double-click on an entry to update plot data.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "import gi\n\ngi.require_version('Gtk', '4.0')\ngi.require_version('Gdk', '4.0')\nfrom gi.repository import Gtk\n\nfrom numpy.random import random\n\nfrom matplotlib.backends.backend_gtk4agg import FigureCanvas  # or gtk4cairo.\nfrom matplotlib.figure import Figure\n\n\nclass DataManager(Gtk.ApplicationWindow):\n    num_rows, num_cols = 20, 10\n\n    data = random((num_rows, num_cols))\n\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        self.set_default_size(600, 600)\n\n        self.set_title('GtkListStore demo')\n\n        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, homogeneous=False,\n                       spacing=8)\n        self.set_child(vbox)\n\n        label = Gtk.Label(label='Double click a row to plot the data')\n        vbox.append(label)\n\n        sw = Gtk.ScrolledWindow()\n        sw.set_has_frame(True)\n        sw.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)\n        sw.set_hexpand(True)\n        sw.set_vexpand(True)\n        vbox.append(sw)\n\n        model = self.create_model()\n        self.treeview = Gtk.TreeView(model=model)\n        self.treeview.connect('row-activated', self.plot_row)\n        sw.set_child(self.treeview)\n\n        # Matplotlib stuff\n        fig = Figure(figsize=(6, 4), layout='constrained')\n\n        self.canvas = FigureCanvas(fig)  # a Gtk.DrawingArea\n        self.canvas.set_hexpand(True)\n        self.canvas.set_vexpand(True)\n        vbox.append(self.canvas)\n        ax = fig.add_subplot()\n        self.line, = ax.plot(self.data[0, :], 'go')  # plot the first row\n\n        self.add_columns()\n\n    def plot_row(self, treeview, path, view_column):\n        ind, = path  # get the index into data\n        points = self.data[ind, :]\n        self.line.set_ydata(points)\n        self.canvas.draw()\n\n    def add_columns(self):\n        for i in range(self.num_cols):\n            column = Gtk.TreeViewColumn(str(i), Gtk.CellRendererText(), text=i)\n            self.treeview.append_column(column)\n\n    def create_model(self):\n        types = [float] * self.num_cols\n        store = Gtk.ListStore(*types)\n        for row in self.data:\n            # Gtk.ListStore.append is broken in PyGObject, so insert manually.\n            it = store.insert(-1)\n            store.set(it, {i: val for i, val in enumerate(row)})\n        return store\n\n\ndef on_activate(app):\n    manager = DataManager(application=app)\n    manager.show()\n\n\napp = Gtk.Application(application_id='org.matplotlib.examples.GTK4Spreadsheet')\napp.connect('activate', on_activate)\napp.run()"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.14.6"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}