{"id":283,"date":"2008-08-19T13:45:18","date_gmt":"2008-08-19T20:45:18","guid":{"rendered":"http:\/\/www.stevenbrown.ca\/blog\/?p=283"},"modified":"2008-08-19T13:46:49","modified_gmt":"2008-08-19T20:46:49","slug":"python-treeview-toggle","status":"publish","type":"post","link":"https:\/\/www.stevenbrown.ca\/blog\/archives\/283","title":{"rendered":"python treeview toggle"},"content":{"rendered":"<p>Had this post sitting around.  Seems finished.  May be helpful to someone.  \/me waves <em>Wand of Publish +1<\/em><\/p>\n<p>I was confused when I was playing around with this basic concept: <em>adding a toggle widget to the treeview in pygtk<\/em>.  The reason for this is an inconsistency in the api model &#8211; or at least how I perceived it.  With a regular toggle button, you create the widget and can manipulate it once it is drawn.  The checkmark is toggled and the &#8220;toggled&#8221; signal is emitted.  I only connect a signal handler to the <em>toggled<\/em> signal after.  However, following this same logic, I created a list with a column of toggle widgets and tried clicking them&#8230; but nothing happened.  The problem here was the toggled value was linked to the list&#8217;s data, and the data wasn&#8217;t actually changing.  Even though the toggle signal was being emitted, the checkmark wasn&#8217;t being toggled because the data wasn&#8217;t changing, so I thought there was a problem with my code and the signal wasn&#8217;t being emitted.  But actually, it would make more sense if it was a &#8220;clicked&#8221; signal that was being emitted, not the &#8220;toggled&#8221; signal.<\/p>\n<p>Example source code:<\/p>\n<pre lang=\"python\">\r\n#!\/usr\/bin\/env python\r\n\r\n# example basictreeviewtoggle.py\r\n\r\nimport pygtk\r\npygtk.require('2.0')\r\nimport gtk\r\nimport gobject\r\n\r\nclass BasicTreeViewToggleExample:\r\n\r\n    # close the window and quit\r\n    def delete_event(self, widget, event, data=None):\r\n        gtk.main_quit()\r\n        return False\r\n\r\n    def column_toggled(self, cell, path, model):\r\n        # get toggled iter, and value at column 0\r\n        iter = model.get_iter((int(path),))\r\n        val = model.get_value(iter, 0)\r\n\r\n        # toggle the value\r\n        val = not val\r\n\r\n        # set new value\r\n        model.set(iter, 0, val)\r\n\r\n\r\n    def __init__(self):\r\n        # create a new window\r\n        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)\r\n        self.window.set_title(\"Basic TreeView Toggle Example\")\r\n        self.window.set_size_request(200, 200)\r\n        self.window.connect(\"delete_event\", self.delete_event)\r\n\r\n        # create a ListStore with two columns to use as the model\r\n        self.model = gtk.ListStore(gobject.TYPE_BOOLEAN, str)\r\n\r\n        # create some list items\r\n        for item in range(5):\r\n            self.model.append([False, 'item %i' % item])\r\n\r\n        # create the TreeView using the model\r\n        self.view = gtk.TreeView(self.model)\r\n\r\n        # create a CellRendererText to render the data\r\n        self.cellrenderer_text = gtk.CellRendererText()\r\n        self.cellrenderer_toggle = gtk.CellRendererToggle()\r\n        self.cellrenderer_toggle.connect('toggled', self.column_toggled, self.model)\r\n\r\n        # create the TreeViewColumns to display the data\r\n        self.tvcolumntext = gtk.TreeViewColumn('TreeViewColumn 1')\r\n        self.tvcolumntoggle = gtk.TreeViewColumn('tog', self.cellrenderer_toggle, active=0)\r\n\r\n        # add the TreeViewColumns to the TreeView\r\n        self.view.append_column(self.tvcolumntoggle)\r\n        self.view.append_column(self.tvcolumntext)\r\n\r\n\r\n\r\n\r\n        # add the cell to the tvcolumn and allow it to expand\r\n        self.tvcolumntoggle.pack_start(self.cellrenderer_toggle, False)\r\n        self.tvcolumntext.pack_start(self.cellrenderer_text, True)\r\n\r\n        \r\n        # set the cell \"text\" attribute to column 0 - retrieve text\r\n        # from that column in treestore\r\n        self.tvcolumntext.add_attribute(self.cellrenderer_text, 'text', 1)\r\n\r\n\r\n        \r\n        # make it searchable\r\n        self.view.set_search_column(1)\r\n\r\n        # Allow sorting on the column\r\n        self.tvcolumntext.set_sort_column_id(1)\r\n\r\n        # Allow drag and drop reordering of rows\r\n        self.view.set_reorderable(True)\r\n\r\n        self.sw = gtk.ScrolledWindow()\r\n        self.sw.add(self.view)\r\n        self.window.add(self.sw)\r\n\r\n        self.window.show_all()\r\n\r\ndef main():\r\n    gtk.main()\r\n\r\nif __name__ == \"__main__\":\r\n    tvexample = BasicTreeViewToggleExample()\r\n    main()\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Had this post sitting around. Seems finished. May be helpful to someone. \/me waves Wand of Publish +1 I was confused when I was playing around with this basic concept: adding a toggle widget to the treeview in pygtk. The reason for this is an inconsistency in the api model &#8211; or at least how&hellip; <a class=\"more-link\" href=\"https:\/\/www.stevenbrown.ca\/blog\/archives\/283\">Continue reading <span class=\"screen-reader-text\">python treeview toggle<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[3,11],"tags":[48,50,42,175,46,31],"class_list":["post-283","post","type-post","status-publish","format-standard","hentry","category-geek","category-projects","tag-code","tag-gtk","tag-how-to","tag-pygtk","tag-python","tag-ui","entry"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p4jEMb-4z","jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/www.stevenbrown.ca\/blog\/wp-json\/wp\/v2\/posts\/283","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.stevenbrown.ca\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.stevenbrown.ca\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.stevenbrown.ca\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.stevenbrown.ca\/blog\/wp-json\/wp\/v2\/comments?post=283"}],"version-history":[{"count":0,"href":"https:\/\/www.stevenbrown.ca\/blog\/wp-json\/wp\/v2\/posts\/283\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.stevenbrown.ca\/blog\/wp-json\/wp\/v2\/media?parent=283"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.stevenbrown.ca\/blog\/wp-json\/wp\/v2\/categories?post=283"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.stevenbrown.ca\/blog\/wp-json\/wp\/v2\/tags?post=283"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}