Python CAD Tutorial 10 - Extending the GTK interface
rss_feed

Python CAD Tutorial 10 - Extending the GTK interface

homeHome
pagesGTK-3
pagespython
pagescad
pagesopengl

View/Download Code

extended gui

We have created some buttons in glade and connected the events so we can switch between the object types ie circle polygon and closed polygons.

Create a class for managing the treeview, this widget is very flexible and can be difficult to work with so abstract the details away. This will be used for showing the layers we have in the project and the objects under each layer.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
import os
import sys
from gi.repository import Gtk, GdkX11, Gdk


class objectList:
    treeview = None
    treemodel = None

    selected = 'workspace'

    def __init__(self, workspace, treeview):
        self.treeview = treeview
        self.workspace = workspace

        # connect the treeview events, capture row selection and row click
        self.treeview.connect('row-activated', self.selection)
        self.treeview.connect('button_press_event', self.show_menu)

        #add a tree store model so everything has a hierarchy
        self.treemodel = Gtk.TreeStore(str)
        self.treeview.set_model(self.treemodel)

        # append colmun headers to the treeview and cell renderer
        column = Gtk.TreeViewColumn("Objects")
        self.treeview.append_column(column)

        cell = Gtk.CellRendererText()
        column.pack_start(cell, False)
        column.add_attribute(cell, "text", 0)

        # populate the objects from the layers
        self.populate()
        self.menu()

    def populate(self):
        self.treemodel.clear()
        for layer in self.workspace.keys():
            tree_iter = self.append(layer)
            for part in self.workspace[layer]:
                self.append(part.name, tree_iter)

    def menu(self):
        self.layer_menu = Gtk.Menu()
        
        self.layer_menu_item = Gtk.MenuItem("Display")
        #self.layer_menu_item.connect("activate", self.toggle_value_handler, 'show')
        self.layer_menu.append(self.layer_menu_item)

        self.layer_menu_item = Gtk.MenuItem("Colour")
        self.layer_menu.append(self.layer_menu_item)

    def show_menu(self, tv, event):
        if event.button == 2:
            model = tv.get_model()
            treeiter = model.get_iter(treepath)
            self.selected = model.get_value(treeiter, 0)
        
        if event.button == 3:
            self.layer_menu.show_all()
            self.layer_menu.popup(None, None, None, None, 1, 0)

    def append(self, name, parent=None):
        myiter = self.treemodel.insert_after(parent, None)
        self.treemodel.set_value(myiter, 0, name)
        return myiter

    def selection(self, tv, treepath, tvcolumn):
        model = tv.get_model()
        treeiter = model.get_iter(treepath)
        self.selected = model.get_value(treeiter, 0)

The workspace class below is a management class. It will contain various methods for working with the visible objects. It will also manage our layers. For now we will add simple functions, for example 'append' (which will add objects to a layer).In the main mycad.py file, you can see that our new polygon is contained and updated through the shape class. Later on we will attach this to our GUI so we can dynamically add primitives as we need them.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
class objectList:
    treeview = None
    treemodel = None

    selected = 'workspace'

    def __init__(self, workspace, treeview):
        self.treeview = treeview
        self.workspace = workspace

        # connect the treeview events, capture row selection and row click
        self.treeview.connect('row-activated', self.selection)
        self.treeview.connect('button_press_event', self.show_menu)

        #add a tree store model so everything has a hierarchy
        self.treemodel = Gtk.TreeStore(str)
        self.treeview.set_model(self.treemodel)

        # append colmun headers to the treeview and cell renderer
        column = Gtk.TreeViewColumn("Objects")
        self.treeview.append_column(column)

        cell = Gtk.CellRendererText()
        column.pack_start(cell, False)
        column.add_attribute(cell, "text", 0)

        # populate the objects from the layers
        self.populate()
        self.menu()

    def populate(self):
        self.treemodel.clear()
        for layer in self.workspace.keys():
            tree_iter = self.append(layer)
            for part in self.workspace[layer]:
                self.append(part.name, tree_iter)

    def menu(self):
        self.layer_menu = Gtk.Menu()
        
        self.layer_menu_item = Gtk.MenuItem("Display")
        #self.layer_menu_item.connect("activate", self.toggle_value_handler, 'show')
        self.layer_menu.append(self.layer_menu_item)

        self.layer_menu_item = Gtk.MenuItem("Colour")
        self.layer_menu.append(self.layer_menu_item)

    def show_menu(self, tv, event):
        if event.button == 2:
            model = tv.get_model()
            treeiter = model.get_iter(treepath)
            self.selected = model.get_value(treeiter, 0)
        
        if event.button == 3:
            self.layer_menu.show_all()
            self.layer_menu.popup(None, None, None, None, 1, 0)

    def append(self, name, parent=None):
        myiter = self.treemodel.insert_after(parent, None)
        self.treemodel.set_value(myiter, 0, name)
        return myiter

    def selection(self, tv, treepath, tvcolumn):
        model = tv.get_model()
        treeiter = model.get_iter(treepath)
        self.selected = model.get_value(treeiter, 0)