Browse Source

Reorganized device list code

Previously, the SelectListStore directly modified the GUI in its
update_items method, which was really just poor form.

This has been corrected by creating a new SelectList to encapsulate all
the GUI elements from the select-stack downward.  This handles showing
the select-none or select-frame elements as appropriate, as well as
adding the list item separators.  It's much nicer than the old way, if I
do say so myself.
Clara Hobbs 7 years ago
parent
commit
9ae4a7c717
3 changed files with 164 additions and 138 deletions
  1. 2
    98
      data/pd-buddy-gtk.ui
  2. 97
    0
      data/select-stack.ui
  3. 65
    40
      pd-buddy-gtk.py

+ 2
- 98
data/pd-buddy-gtk.ui View File

@@ -34,108 +34,12 @@
34 34
                 <property name="visible">True</property>
35 35
                 <property name="can_focus">False</property>
36 36
                 <child>
37
-                  <object class="GtkBox">
37
+                  <object class="GtkBox" id="select-box">
38 38
                     <property name="visible">True</property>
39 39
                     <property name="can_focus">False</property>
40 40
                     <property name="orientation">vertical</property>
41 41
                     <child>
42
-                      <object class="GtkStack" id="select-stack">
43
-                        <property name="visible">True</property>
44
-                        <property name="can_focus">False</property>
45
-                        <property name="vexpand">True</property>
46
-                        <child>
47
-                          <object class="GtkBox" id="select-none">
48
-                            <property name="visible">True</property>
49
-                            <property name="can_focus">False</property>
50
-                            <property name="halign">center</property>
51
-                            <property name="valign">center</property>
52
-                            <property name="margin_bottom">22</property>
53
-                            <property name="orientation">vertical</property>
54
-                            <child>
55
-                              <object class="GtkLabel" id="select-none-header">
56
-                                <property name="visible">True</property>
57
-                                <property name="can_focus">False</property>
58
-                                <property name="margin_bottom">12</property>
59
-                                <property name="label" translatable="yes">No devices found</property>
60
-                                <attributes>
61
-                                  <attribute name="weight" value="bold"/>
62
-                                  <attribute name="scale" value="2"/>
63
-                                </attributes>
64
-                                <style>
65
-                                  <class name="dim-label"/>
66
-                                </style>
67
-                              </object>
68
-                              <packing>
69
-                                <property name="expand">False</property>
70
-                                <property name="fill">True</property>
71
-                                <property name="position">0</property>
72
-                              </packing>
73
-                            </child>
74
-                            <child>
75
-                              <object class="GtkLabel" id="select-none-text">
76
-                                <property name="visible">True</property>
77
-                                <property name="can_focus">False</property>
78
-                                <property name="label" translatable="yes">All connected PD Buddy devices will appear here</property>
79
-                                <style>
80
-                                  <class name="dim-label"/>
81
-                                </style>
82
-                              </object>
83
-                              <packing>
84
-                                <property name="expand">False</property>
85
-                                <property name="fill">True</property>
86
-                                <property name="position">1</property>
87
-                              </packing>
88
-                            </child>
89
-                          </object>
90
-                          <packing>
91
-                            <property name="name">page1</property>
92
-                            <property name="title" translatable="yes">page1</property>
93
-                          </packing>
94
-                        </child>
95
-                        <child>
96
-                          <object class="GtkFrame" id="select-frame">
97
-                            <property name="visible">True</property>
98
-                            <property name="can_focus">False</property>
99
-                            <property name="halign">center</property>
100
-                            <property name="valign">start</property>
101
-                            <property name="margin_left">50</property>
102
-                            <property name="margin_right">50</property>
103
-                            <property name="margin_top">22</property>
104
-                            <property name="margin_bottom">22</property>
105
-                            <property name="hexpand">False</property>
106
-                            <property name="label_xalign">0</property>
107
-                            <property name="shadow_type">in</property>
108
-                            <child>
109
-                              <object class="GtkAlignment">
110
-                                <property name="visible">True</property>
111
-                                <property name="can_focus">False</property>
112
-                                <child>
113
-                                  <object class="GtkListBox" id="select-list">
114
-                                    <property name="width_request">442</property>
115
-                                    <property name="visible">True</property>
116
-                                    <property name="can_focus">False</property>
117
-                                    <property name="selection_mode">none</property>
118
-                                    <signal name="row-activated" handler="on_select_list_row_activated" swapped="no"/>
119
-                                  </object>
120
-                                </child>
121
-                              </object>
122
-                            </child>
123
-                            <child type="label_item">
124
-                              <placeholder/>
125
-                            </child>
126
-                          </object>
127
-                          <packing>
128
-                            <property name="name">page0</property>
129
-                            <property name="title" translatable="yes">page0</property>
130
-                            <property name="position">1</property>
131
-                          </packing>
132
-                        </child>
133
-                      </object>
134
-                      <packing>
135
-                        <property name="expand">False</property>
136
-                        <property name="fill">True</property>
137
-                        <property name="position">0</property>
138
-                      </packing>
42
+                      <placeholder/>
139 43
                     </child>
140 44
                   </object>
141 45
                 </child>

+ 97
- 0
data/select-stack.ui View File

@@ -0,0 +1,97 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<!-- Generated with glade 3.20.0 -->
3
+<interface>
4
+  <requires lib="gtk+" version="3.20"/>
5
+  <object class="GtkStack" id="select-stack">
6
+    <property name="visible">True</property>
7
+    <property name="can_focus">False</property>
8
+    <property name="vexpand">True</property>
9
+    <child>
10
+      <object class="GtkBox" id="select-none">
11
+        <property name="visible">True</property>
12
+        <property name="can_focus">False</property>
13
+        <property name="halign">center</property>
14
+        <property name="valign">center</property>
15
+        <property name="margin_bottom">22</property>
16
+        <property name="orientation">vertical</property>
17
+        <child>
18
+          <object class="GtkLabel" id="select-none-header">
19
+            <property name="visible">True</property>
20
+            <property name="can_focus">False</property>
21
+            <property name="margin_bottom">12</property>
22
+            <property name="label" translatable="yes">No devices found</property>
23
+            <attributes>
24
+              <attribute name="weight" value="bold"/>
25
+              <attribute name="scale" value="2"/>
26
+            </attributes>
27
+            <style>
28
+              <class name="dim-label"/>
29
+            </style>
30
+          </object>
31
+          <packing>
32
+            <property name="expand">False</property>
33
+            <property name="fill">True</property>
34
+            <property name="position">0</property>
35
+          </packing>
36
+        </child>
37
+        <child>
38
+          <object class="GtkLabel" id="select-none-text">
39
+            <property name="visible">True</property>
40
+            <property name="can_focus">False</property>
41
+            <property name="label" translatable="yes">All connected PD Buddy devices will appear here</property>
42
+            <style>
43
+              <class name="dim-label"/>
44
+            </style>
45
+          </object>
46
+          <packing>
47
+            <property name="expand">False</property>
48
+            <property name="fill">True</property>
49
+            <property name="position">1</property>
50
+          </packing>
51
+        </child>
52
+      </object>
53
+      <packing>
54
+        <property name="name">page1</property>
55
+        <property name="title" translatable="yes">page1</property>
56
+      </packing>
57
+    </child>
58
+    <child>
59
+      <object class="GtkFrame" id="select-frame">
60
+        <property name="visible">True</property>
61
+        <property name="can_focus">False</property>
62
+        <property name="halign">center</property>
63
+        <property name="valign">start</property>
64
+        <property name="margin_left">50</property>
65
+        <property name="margin_right">50</property>
66
+        <property name="margin_top">22</property>
67
+        <property name="margin_bottom">22</property>
68
+        <property name="hexpand">False</property>
69
+        <property name="label_xalign">0</property>
70
+        <property name="shadow_type">in</property>
71
+        <child>
72
+          <object class="GtkAlignment">
73
+            <property name="visible">True</property>
74
+            <property name="can_focus">False</property>
75
+            <child>
76
+              <object class="GtkListBox" id="select-list">
77
+                <property name="width_request">442</property>
78
+                <property name="visible">True</property>
79
+                <property name="can_focus">False</property>
80
+                <property name="selection_mode">none</property>
81
+                <signal name="row-activated" handler="on_select_list_row_activated" swapped="no"/>
82
+              </object>
83
+            </child>
84
+          </object>
85
+        </child>
86
+        <child type="label_item">
87
+          <placeholder/>
88
+        </child>
89
+      </object>
90
+      <packing>
91
+        <property name="name">page0</property>
92
+        <property name="title" translatable="yes">page0</property>
93
+        <property name="position">1</property>
94
+      </packing>
95
+    </child>
96
+  </object>
97
+</interface>

+ 65
- 40
pd-buddy-gtk.py View File

@@ -9,17 +9,6 @@ gi.require_version('Gtk', '3.0')
9 9
 from gi.repository import Gtk, Gio, GObject, GLib
10 10
 
11 11
 
12
-def update_header_func(row, before, data):
13
-    """Add a separator header to all rows but the first one"""
14
-    if before is None:
15
-        row.set_header(None)
16
-        return
17
-
18
-    current = row.get_header()
19
-    if current is None:
20
-        current = Gtk.Separator.new(Gtk.Orientation.HORIZONTAL)
21
-        row.set_header(current)
22
-
23 12
 def pdb_send_message(sp, message):
24 13
     """Send a message over the serial port and return the response"""
25 14
     # Open the serial port
@@ -46,16 +35,6 @@ class ListRowModel(GObject.GObject):
46 35
 
47 36
 class SelectListStore(Gio.ListStore):
48 37
 
49
-    def __init__(self, stack, list_empty, list_frame):
50
-        Gio.ListStore.__init__(self)
51
-
52
-        self.stack = stack
53
-        self.list_empty = list_empty
54
-        self.list_frame = list_frame
55
-
56
-        self.update_items()
57
-        GLib.timeout_add(1000, self.update_items)
58
-
59 38
     def update_items(self):
60 39
         # Get a list of serial ports
61 40
         serports = list(serial.tools.list_ports.grep("1209:0001"))
@@ -81,38 +60,86 @@ class SelectListStore(Gio.ListStore):
81 60
             if port is not None:
82 61
                 self.append(ListRowModel(port))
83 62
 
63
+
64
+class SelectList(Gtk.Box):
65
+    __gsignals__ = {
66
+        'row-activated': (GObject.SIGNAL_RUN_FIRST, None,
67
+                      (object,))
68
+    }
69
+
70
+    def __init__(self):
71
+        Gtk.Box.__init__(self)
72
+
73
+        self._model = None
74
+
75
+        self._builder = Gtk.Builder()
76
+        self._builder.add_from_file("data/select-stack.ui")
77
+        self._builder.connect_signals(self)
78
+
79
+        sl = self._builder.get_object("select-list")
80
+
81
+        # Add separators to the list
82
+        sl.set_header_func(self._update_header_func, None)
83
+
84
+        self.pack_start(self._builder.get_object("select-stack"), True, True, 0)
85
+        self.show_all()
86
+
87
+    def _update_header_func(self, row, before, data):
88
+        """Add a separator header to all rows but the first one"""
89
+        if before is None:
90
+            row.set_header(None)
91
+            return
92
+
93
+        current = row.get_header()
94
+        if current is None:
95
+            current = Gtk.Separator.new(Gtk.Orientation.HORIZONTAL)
96
+            row.set_header(current)
97
+
98
+    def bind_model(self, model, func):
99
+        self._builder.get_object("select-list").bind_model(model, func)
100
+        self._model = model
101
+
102
+        self._reload()
103
+        GLib.timeout_add(1000, self._reload)
104
+
105
+    def _reload(self):
106
+        self._model.update_items()
107
+
84 108
         # Set the visible child
85
-        # FIXME: This is rather poor organization
86
-        if self.get_n_items():
87
-            self.stack.set_visible_child(self.list_frame)
109
+        stack = self._builder.get_object("select-stack")
110
+        if self._model.get_n_items():
111
+            stack.set_visible_child(self._builder.get_object("select-frame"))
88 112
         else:
89
-            self.stack.set_visible_child(self.list_empty)
113
+            stack.set_visible_child(self._builder.get_object("select-none"))
90 114
 
91 115
         return True
92 116
 
117
+    def on_select_list_row_activated(self, box, row):
118
+        self.emit("row-activated", row.model.serport)
119
+
93 120
 
94 121
 class SelectListRow(Gtk.ListBoxRow):
95 122
 
96
-    def __init__(self, lrm):
123
+    def __init__(self, model):
97 124
         Gtk.EventBox.__init__(self)
98 125
 
99
-        self.serial_port = lrm.serport
126
+        self.model = model
100 127
 
101 128
         self._builder = Gtk.Builder()
102 129
         self._builder.add_from_file("data/select-list-row.ui")
103 130
         self._builder.connect_signals(self)
104 131
 
105 132
         name = self._builder.get_object("name")
106
-        name.set_text(self.serial_port.description)
133
+        name.set_text(self.model.serport.description)
107 134
 
108 135
         device = self._builder.get_object("device")
109
-        device.set_text(self.serial_port.device)
136
+        device.set_text(self.model.serport.device)
110 137
 
111 138
         self.add(self._builder.get_object("grid"))
112 139
         self.show_all()
113 140
 
114 141
     def on_identify_clicked(self, button):
115
-        pdb_send_message(self.serial_port, 'identify')
142
+        pdb_send_message(self.model.serport, 'identify')
116 143
 
117 144
 
118 145
 class Handler:
@@ -122,27 +149,25 @@ class Handler:
122 149
 
123 150
     def on_pdb_window_realize(self, *args):
124 151
         # Get the list
125
-        sl = self.builder.get_object("select-list")
126
-        ss = self.builder.get_object("select-stack")
127
-        se = self.builder.get_object("select-none")
128
-        sf = self.builder.get_object("select-frame")
152
+        sb = self.builder.get_object("select-box")
153
+        sl = SelectList()
154
+        sb.pack_start(sl, True, True, 0)
129 155
 
130
-        liststore = SelectListStore(ss, se, sf)
156
+        liststore = SelectListStore()
131 157
 
132 158
         sl.bind_model(liststore, SelectListRow)
133 159
 
134
-        # Add separators to the list
135
-        sl.set_header_func(update_header_func, None)
160
+        sl.connect("row-activated", self.on_select_list_row_activated)
136 161
 
137 162
     def on_pdb_window_delete_event(self, *args):
138 163
         Gtk.main_quit(*args)
139 164
 
140
-    def on_select_list_row_activated(self, box, row):
165
+    def on_select_list_row_activated(self, selectlist, serport):
141 166
         # Get voltage and current widgets
142 167
         voltage = self.builder.get_object("voltage-combobox")
143 168
         current = self.builder.get_object("current-spinbutton")
144 169
 
145
-        self.serial_port = row.serial_port
170
+        self.serial_port = serport
146 171
 
147 172
         pdb_send_message(self.serial_port, 'load')
148 173
         tmpcfg = pdb_send_message(self.serial_port, 'get_tmpcfg')
@@ -170,7 +195,7 @@ class Handler:
170 195
         # Show the Sink page
171 196
         hst = self.builder.get_object("header-stack")
172 197
         hsink = self.builder.get_object("header-sink")
173
-        hsink.set_subtitle(row.serial_port.device)
198
+        hsink.set_subtitle(serport.device)
174 199
         hst.set_visible_child(hsink)
175 200
 
176 201
         st = self.builder.get_object("stack")

Loading…
Cancel
Save