]>
Commit | Line | Data |
---|---|---|
3f63165c UH |
1 | /* |
2 | * This file is part of the sigrok project. | |
3 | * | |
4 | * Copyright (C) 2011 Gareth McMullin <gareth@blacksphere.co.nz> | |
5 | * | |
6 | * This program is free software: you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License as published by | |
8 | * the Free Software Foundation, either version 3 of the License, or | |
9 | * (at your option) any later version. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | * GNU General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
18 | */ | |
19 | ||
20 | #include <stdlib.h> | |
21 | ||
22 | #include <sigrok.h> | |
23 | ||
24 | #include <gtk/gtk.h> | |
25 | ||
26 | #include <stdlib.h> | |
27 | ||
28 | #include "sigrok-gtk.h" | |
29 | ||
30 | enum { | |
43132a90 | 31 | DEV_PROP_HWCAP, |
3f63165c UH |
32 | DEV_PROP_TYPE, |
33 | DEV_PROP_SHORTNAME, | |
34 | DEV_PROP_DESCRIPTION, | |
35 | DEV_PROP_IS_TEXT, | |
36 | DEV_PROP_TEXTVALUE, | |
37 | DEV_PROP_BOOLVALUE, | |
38 | MAX_DEV_PROP | |
39 | }; | |
40 | ||
41 | static void prop_edited(GtkCellRendererText *cel, gchar *path, gchar *text, | |
42 | GtkListStore *props) | |
43 | { | |
44 | (void)cel; | |
45 | ||
ffe80b55 | 46 | struct sr_dev *dev = g_object_get_data(G_OBJECT(props), "dev"); |
3f63165c UH |
47 | GtkTreeIter iter; |
48 | int type, cap; | |
49 | guint64 tmp_u64; | |
50 | int ret = SR_ERR; | |
51 | ||
52 | gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(props), &iter, path); | |
53 | gtk_tree_model_get(GTK_TREE_MODEL(props), &iter, | |
43132a90 | 54 | DEV_PROP_HWCAP, &cap, |
3f63165c UH |
55 | DEV_PROP_TYPE, &type, -1); |
56 | ||
57 | switch (type) { | |
58 | case SR_T_UINT64: | |
59 | if (sr_parse_sizestring(text, &tmp_u64) != SR_OK) | |
60 | return; | |
61 | ||
a4f48bca | 62 | ret = dev->driver->dev_config_set(dev->driver_index, |
31345264 | 63 | cap, &tmp_u64); |
3f63165c UH |
64 | break; |
65 | case SR_T_CHAR: | |
a4f48bca | 66 | ret = dev->driver->dev_config_set(dev->driver_index, cap, text); |
3f63165c UH |
67 | break; |
68 | /* SR_T_BOOL will be handled by prop_toggled */ | |
69 | } | |
70 | ||
71 | if (!ret) | |
72 | gtk_list_store_set(props, &iter, DEV_PROP_TEXTVALUE, text, -1); | |
73 | } | |
74 | ||
75 | static void prop_toggled(GtkCellRendererToggle *cel, gchar *path, | |
76 | GtkListStore *props) | |
77 | { | |
ffe80b55 | 78 | struct sr_dev *dev = g_object_get_data(G_OBJECT(props), "dev"); |
3f63165c UH |
79 | GtkTreeIter iter; |
80 | int type, cap; | |
81 | int ret; | |
82 | gboolean val; | |
83 | gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(props), &iter, path); | |
84 | gtk_tree_model_get(GTK_TREE_MODEL(props), &iter, | |
43132a90 | 85 | DEV_PROP_HWCAP, &cap, |
3f63165c UH |
86 | DEV_PROP_TYPE, &type, -1); |
87 | ||
88 | val = !gtk_cell_renderer_toggle_get_active(cel); | |
a4f48bca | 89 | ret = dev->driver->dev_config_set(dev->driver_index, cap, |
31345264 | 90 | GINT_TO_POINTER(val)); |
3f63165c UH |
91 | |
92 | if (!ret) | |
93 | gtk_list_store_set(props, &iter, DEV_PROP_BOOLVALUE, val, -1); | |
94 | } | |
95 | ||
96 | void dev_prop_bool_data_func(GtkCellLayout *cell_layout, | |
97 | GtkCellRenderer *cell, | |
98 | GtkTreeModel *tree_model, | |
99 | GtkTreeIter *iter, | |
100 | gpointer data) | |
101 | { | |
102 | (void)cell_layout; | |
103 | (void)data; | |
104 | ||
105 | gboolean istext, val; | |
106 | gtk_tree_model_get(tree_model, iter, | |
107 | DEV_PROP_IS_TEXT, &istext, | |
108 | DEV_PROP_BOOLVALUE, &val, -1); | |
109 | g_object_set(G_OBJECT(cell), "visible", !istext, "active", val, NULL); | |
110 | } | |
111 | ||
112 | static void dev_set_options(GtkAction *action, GtkWindow *parent) | |
113 | { | |
114 | (void)action; | |
115 | ||
ffe80b55 UH |
116 | struct sr_dev *dev = g_object_get_data(G_OBJECT(parent), "dev"); |
117 | if (!dev) | |
3f63165c UH |
118 | return; |
119 | ||
120 | GtkWidget *dialog = gtk_dialog_new_with_buttons("Device Properties", | |
121 | parent, GTK_DIALOG_MODAL, | |
122 | GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, | |
123 | NULL); | |
124 | GtkWidget *sw = gtk_scrolled_window_new(NULL, NULL); | |
125 | gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), | |
126 | GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); | |
127 | gtk_widget_set_size_request(sw, 300, 200); | |
128 | GtkWidget *tv = gtk_tree_view_new(); | |
129 | gtk_container_add(GTK_CONTAINER(sw), tv); | |
130 | gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), sw, | |
131 | TRUE, TRUE, 0); | |
132 | ||
133 | /* Populate list store with config options */ | |
134 | GtkListStore *props = gtk_list_store_new(MAX_DEV_PROP, | |
135 | G_TYPE_INT, G_TYPE_INT, | |
136 | G_TYPE_STRING, G_TYPE_STRING, | |
137 | G_TYPE_BOOLEAN, G_TYPE_STRING, | |
138 | G_TYPE_BOOLEAN); | |
139 | gtk_tree_view_set_model(GTK_TREE_VIEW(tv), GTK_TREE_MODEL(props)); | |
a4f48bca | 140 | int *hwcaps = dev->driver->hwcap_get_all(); |
3f63165c UH |
141 | int cap; |
142 | GtkTreeIter iter; | |
43132a90 | 143 | for (cap = 0; hwcaps[cap]; cap++) { |
3f63165c | 144 | struct sr_hwcap_option *hwo; |
43132a90 | 145 | if (!(hwo = sr_hw_hwcap_get(hwcaps[cap]))) |
3f63165c UH |
146 | continue; |
147 | gtk_list_store_append(props, &iter); | |
148 | gtk_list_store_set(props, &iter, | |
43132a90 | 149 | DEV_PROP_HWCAP, hwcaps[cap], |
3f63165c UH |
150 | DEV_PROP_TYPE, hwo->type, |
151 | DEV_PROP_SHORTNAME, hwo->shortname, | |
152 | DEV_PROP_DESCRIPTION, hwo->description, | |
153 | DEV_PROP_IS_TEXT, hwo->type != SR_T_BOOL, | |
154 | -1); | |
155 | } | |
156 | ||
157 | /* Popup tooltop containing description if mouse hovers */ | |
158 | gtk_tree_view_set_tooltip_column(GTK_TREE_VIEW(tv), | |
159 | DEV_PROP_DESCRIPTION); | |
160 | ||
161 | /* Save device with list so that property can be set by edited | |
162 | * handler. */ | |
ffe80b55 | 163 | g_object_set_data(G_OBJECT(props), "dev", dev); |
3f63165c UH |
164 | |
165 | /* Add columns to the tree view */ | |
166 | GtkTreeViewColumn *col; | |
167 | col = gtk_tree_view_column_new_with_attributes("Property", | |
168 | gtk_cell_renderer_text_new(), | |
169 | "text", DEV_PROP_SHORTNAME, NULL); | |
170 | gtk_tree_view_append_column(GTK_TREE_VIEW(tv), col); | |
171 | /* We pack both a text and toggle renderer. Only one will be visible. | |
172 | * depending on type. | |
173 | */ | |
174 | GtkCellRenderer *cel = gtk_cell_renderer_text_new(); | |
175 | g_object_set(cel, "editable", TRUE, NULL); | |
176 | g_signal_connect(cel, "edited", G_CALLBACK(prop_edited), props); | |
177 | col = gtk_tree_view_column_new_with_attributes("Value", | |
178 | cel, "text", DEV_PROP_TEXTVALUE, | |
179 | "visible", DEV_PROP_IS_TEXT, NULL); | |
180 | cel = gtk_cell_renderer_toggle_new(); | |
181 | g_signal_connect(cel, "toggled", G_CALLBACK(prop_toggled), props); | |
182 | gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(col), cel, TRUE); | |
183 | gtk_cell_layout_set_cell_data_func(GTK_CELL_LAYOUT(col), cel, | |
184 | dev_prop_bool_data_func, NULL, NULL); | |
185 | gtk_tree_view_append_column(GTK_TREE_VIEW(tv), col); | |
186 | ||
187 | ||
188 | gtk_widget_show_all(dialog); | |
189 | gtk_dialog_run(GTK_DIALOG(dialog)); | |
190 | ||
191 | gtk_widget_destroy(dialog); | |
192 | } | |
193 | ||
194 | enum { | |
195 | PROBE_NUMBER, | |
196 | PROBE_ENABLED, | |
197 | PROBE_NAME, | |
198 | PROBE_TRIGGER, | |
199 | MAX_PROBE | |
200 | }; | |
201 | ||
202 | static void probe_toggled(GtkCellRenderer *cel, gchar *path, | |
203 | GtkTreeModel *probes) | |
204 | { | |
ffe80b55 | 205 | struct sr_dev *dev = g_object_get_data(G_OBJECT(probes), "dev"); |
3f63165c UH |
206 | GtkTreeIter iter; |
207 | struct sr_probe *probe; | |
208 | gint i; | |
209 | gboolean en; | |
210 | ||
211 | (void)cel; | |
212 | ||
213 | gtk_tree_model_get_iter_from_string(probes, &iter, path); | |
214 | gtk_tree_model_get(probes, &iter, PROBE_NUMBER, &i, | |
215 | PROBE_ENABLED, &en, -1); | |
ffe80b55 | 216 | probe = sr_dev_probe_find(dev, i); |
3f63165c UH |
217 | probe->enabled = !en; |
218 | gtk_list_store_set(GTK_LIST_STORE(probes), &iter, | |
219 | PROBE_ENABLED, probe->enabled, -1); | |
220 | } | |
221 | ||
222 | static void probe_named(GtkCellRendererText *cel, gchar *path, gchar *text, | |
223 | GtkTreeModel *probes) | |
224 | { | |
ffe80b55 | 225 | struct sr_dev *dev = g_object_get_data(G_OBJECT(probes), "dev"); |
3f63165c UH |
226 | GtkTreeIter iter; |
227 | gint i; | |
228 | ||
229 | (void)cel; | |
230 | ||
231 | gtk_tree_model_get_iter_from_string(probes, &iter, path); | |
232 | gtk_tree_model_get(probes, &iter, PROBE_NUMBER, &i, -1); | |
4bedfdb7 | 233 | sr_dev_probe_name_set(dev, i, text); |
3f63165c UH |
234 | gtk_list_store_set(GTK_LIST_STORE(probes), &iter, PROBE_NAME, text, -1); |
235 | } | |
236 | ||
237 | static void probe_trigger_set(GtkCellRendererText *cel, gchar *path, | |
238 | gchar *text, GtkTreeModel *probes) | |
239 | { | |
ffe80b55 | 240 | struct sr_dev *dev = g_object_get_data(G_OBJECT(probes), "dev"); |
3f63165c UH |
241 | GtkTreeIter iter; |
242 | gint i; | |
243 | ||
244 | (void)cel; | |
245 | ||
246 | gtk_tree_model_get_iter_from_string(probes, &iter, path); | |
247 | gtk_tree_model_get(probes, &iter, PROBE_NUMBER, &i, -1); | |
ffe80b55 | 248 | sr_dev_trigger_set(dev, i, text); |
3f63165c UH |
249 | gtk_list_store_set(GTK_LIST_STORE(probes), &iter, |
250 | PROBE_TRIGGER, text, -1); | |
251 | } | |
252 | ||
253 | static void dev_set_probes(GtkAction *action, GtkWindow *parent) | |
254 | { | |
255 | (void)action; | |
256 | ||
ffe80b55 UH |
257 | struct sr_dev *dev = g_object_get_data(G_OBJECT(parent), "dev"); |
258 | if (!dev) | |
3f63165c UH |
259 | return; |
260 | ||
261 | GtkWidget *dialog = gtk_dialog_new_with_buttons("Configure Probes", | |
262 | parent, GTK_DIALOG_MODAL, | |
263 | GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, | |
264 | NULL); | |
265 | GtkWidget *sw = gtk_scrolled_window_new(NULL, NULL); | |
266 | gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), | |
267 | GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); | |
268 | gtk_widget_set_size_request(sw, 300, 200); | |
269 | GtkWidget *tv = gtk_tree_view_new(); | |
270 | gtk_container_add(GTK_CONTAINER(sw), tv); | |
271 | gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), sw, | |
272 | TRUE, TRUE, 0); | |
273 | ||
274 | /* Populate list store with probe options */ | |
275 | GtkListStore *probes = gtk_list_store_new(MAX_PROBE, | |
276 | G_TYPE_INT, G_TYPE_BOOLEAN, | |
277 | G_TYPE_STRING, GTK_TYPE_STRING); | |
278 | gtk_tree_view_set_model(GTK_TREE_VIEW(tv), GTK_TREE_MODEL(probes)); | |
279 | GtkTreeIter iter; | |
280 | GSList *p; | |
281 | int i; | |
ffe80b55 | 282 | for (p = dev->probes, i = 1; p; p = g_slist_next(p), i++) { |
3f63165c UH |
283 | struct sr_probe *probe = p->data; |
284 | gtk_list_store_append(probes, &iter); | |
285 | gtk_list_store_set(probes, &iter, PROBE_NUMBER, i, | |
286 | PROBE_ENABLED, probe->enabled, | |
287 | PROBE_NAME, probe->name, | |
288 | PROBE_TRIGGER, probe->trigger, | |
289 | -1); | |
290 | } | |
291 | ||
292 | /* Save device with list so that property can be set by edited | |
293 | * handler. */ | |
ffe80b55 | 294 | g_object_set_data(G_OBJECT(probes), "dev", dev); |
3f63165c UH |
295 | |
296 | /* Add columns to the tree view */ | |
297 | GtkTreeViewColumn *col; | |
298 | col = gtk_tree_view_column_new_with_attributes("Probe", | |
299 | gtk_cell_renderer_text_new(), | |
300 | "text", PROBE_NUMBER, NULL); | |
301 | gtk_tree_view_append_column(GTK_TREE_VIEW(tv), col); | |
302 | GtkCellRenderer *cel = gtk_cell_renderer_toggle_new(); | |
303 | g_object_set(cel, "activatable", TRUE, NULL); | |
304 | g_signal_connect(cel, "toggled", G_CALLBACK(probe_toggled), probes); | |
305 | col = gtk_tree_view_column_new_with_attributes("En", | |
306 | cel, "active", PROBE_ENABLED, NULL); | |
307 | gtk_tree_view_append_column(GTK_TREE_VIEW(tv), col); | |
308 | cel = gtk_cell_renderer_text_new(); | |
309 | g_object_set(cel, "editable", TRUE, NULL); | |
310 | g_signal_connect(cel, "edited", G_CALLBACK(probe_named), probes); | |
311 | col = gtk_tree_view_column_new_with_attributes("Signal Name", cel, | |
312 | "text", PROBE_NAME, | |
313 | "sensitive", PROBE_ENABLED, NULL); | |
314 | gtk_tree_view_column_set_resizable(col, TRUE); | |
315 | gtk_tree_view_append_column(GTK_TREE_VIEW(tv), col); | |
316 | cel = gtk_cell_renderer_text_new(); | |
317 | g_object_set(cel, "editable", TRUE, NULL); | |
318 | g_signal_connect(cel, "edited", G_CALLBACK(probe_trigger_set), probes); | |
319 | col = gtk_tree_view_column_new_with_attributes("Trigger", cel, | |
320 | "text", PROBE_TRIGGER, | |
321 | "sensitive", PROBE_ENABLED, NULL); | |
322 | gtk_tree_view_append_column(GTK_TREE_VIEW(tv), col); | |
323 | ||
324 | gtk_widget_show_all(dialog); | |
325 | gtk_dialog_run(GTK_DIALOG(dialog)); | |
326 | ||
327 | gtk_widget_destroy(dialog); | |
328 | } | |
329 | ||
330 | static void capture_run(GtkAction *action, GObject *parent) | |
331 | { | |
332 | (void)action; | |
333 | ||
ffe80b55 | 334 | struct sr_dev *dev = g_object_get_data(G_OBJECT(parent), "dev"); |
3f63165c UH |
335 | GtkEntry *timesamples = g_object_get_data(parent, "timesamples"); |
336 | GtkComboBox *timeunit = g_object_get_data(parent, "timeunit"); | |
337 | gint i = gtk_combo_box_get_active(timeunit); | |
338 | guint64 time_msec = 0; | |
339 | guint64 limit_samples = 0; | |
340 | ||
341 | switch (i) { | |
342 | case 0: /* Samples */ | |
343 | sr_parse_sizestring(gtk_entry_get_text(timesamples), | |
344 | &limit_samples); | |
345 | break; | |
346 | case 1: /* Milliseconds */ | |
347 | time_msec = strtoull(gtk_entry_get_text(timesamples), NULL, 10); | |
348 | break; | |
349 | case 2: /* Seconds */ | |
350 | time_msec = strtoull(gtk_entry_get_text(timesamples), NULL, 10) | |
351 | * 1000; | |
352 | break; | |
353 | } | |
354 | ||
355 | if (time_msec) { | |
6054cbb8 | 356 | if (sr_driver_hwcap_exists(dev->driver, SR_HWCAP_LIMIT_MSEC)) { |
a4f48bca | 357 | if (dev->driver->dev_config_set(dev->driver_index, |
31345264 UH |
358 | SR_HWCAP_LIMIT_MSEC, |
359 | &time_msec) != SR_OK) { | |
3f63165c UH |
360 | g_critical("Failed to configure time limit."); |
361 | sr_session_destroy(); | |
362 | return; | |
363 | } | |
364 | } else { | |
365 | /* time limit set, but device doesn't support this... | |
366 | * convert to samples based on the samplerate. | |
367 | */ | |
368 | limit_samples = 0; | |
ffe80b55 | 369 | if (sr_dev_has_hwcap(dev, SR_HWCAP_SAMPLERATE)) { |
3f63165c | 370 | guint64 tmp_u64; |
a4f48bca UH |
371 | tmp_u64 = *((uint64_t *)dev->driver->dev_info_get( |
372 | dev->driver_index, | |
3f63165c UH |
373 | SR_DI_CUR_SAMPLERATE)); |
374 | limit_samples = tmp_u64 * time_msec / (uint64_t) 1000; | |
375 | } | |
376 | if (limit_samples == 0) { | |
377 | g_critical("Not enough time at this samplerate."); | |
378 | return; | |
379 | } | |
380 | ||
a4f48bca | 381 | if (dev->driver->dev_config_set(dev->driver_index, |
31345264 UH |
382 | SR_HWCAP_LIMIT_SAMPLES, |
383 | &limit_samples) != SR_OK) { | |
3f63165c UH |
384 | g_critical("Failed to configure time-based sample limit."); |
385 | return; | |
386 | } | |
387 | } | |
388 | } | |
389 | if (limit_samples) { | |
a4f48bca | 390 | if (dev->driver->dev_config_set(dev->driver_index, |
31345264 UH |
391 | SR_HWCAP_LIMIT_SAMPLES, |
392 | &limit_samples) != SR_OK) { | |
3f63165c UH |
393 | g_critical("Failed to configure sample limit."); |
394 | return; | |
395 | } | |
396 | } | |
397 | ||
a4f48bca | 398 | if (dev->driver->dev_config_set(dev->driver_index, |
97fe0e2b | 399 | SR_HWCAP_PROBECONFIG, (char *)dev->probes) != SR_OK) { |
3f63165c UH |
400 | printf("Failed to configure probes.\n"); |
401 | sr_session_destroy(); | |
402 | return; | |
403 | } | |
404 | ||
405 | if (sr_session_start() != SR_OK) { | |
406 | g_critical("Failed to start session."); | |
407 | return; | |
408 | } | |
409 | ||
410 | sr_session_run(); | |
411 | } | |
412 | ||
413 | static void dev_file_open(GtkAction *action, GtkWindow *parent) | |
414 | { | |
415 | (void)action; | |
416 | static GtkWidget *dialog; | |
417 | const gchar *filename; | |
418 | ||
419 | if(!dialog) | |
420 | dialog = gtk_file_chooser_dialog_new("Open", parent, | |
421 | GTK_FILE_CHOOSER_ACTION_OPEN, | |
422 | GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, | |
423 | GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); | |
424 | g_signal_connect(dialog, "delete-event", | |
425 | G_CALLBACK(gtk_widget_hide_on_delete), | |
426 | NULL); | |
427 | ||
428 | if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_ACCEPT) { | |
429 | /* Dialog was cancelled or closed */ | |
430 | gtk_widget_hide(dialog); | |
431 | return; | |
432 | } | |
433 | ||
434 | gtk_widget_hide(dialog); | |
435 | ||
436 | filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); | |
437 | load_input_file(parent, filename); | |
438 | } | |
439 | ||
440 | void toggle_log(GtkToggleAction *action, GObject *parent) | |
441 | { | |
442 | GtkWidget *log = g_object_get_data(parent, "logview"); | |
443 | gtk_widget_set_visible(log, gtk_toggle_action_get_active(action)); | |
444 | } | |
445 | ||
446 | void zoom_in(GtkAction *action, GObject *parent) | |
447 | { | |
448 | (void)action; | |
449 | ||
450 | GtkWidget *sigview = g_object_get_data(parent, "sigview"); | |
451 | sigview_zoom(sigview, 1.5, 0); | |
452 | } | |
453 | ||
454 | void zoom_out(GtkAction *action, GObject *parent) | |
455 | { | |
456 | (void)action; | |
457 | ||
458 | GtkWidget *sigview = g_object_get_data(parent, "sigview"); | |
459 | sigview_zoom(sigview, 1/1.5, 0); | |
460 | } | |
461 | ||
462 | void zoom_fit(GtkAction *action, GObject *parent) | |
463 | { | |
464 | (void)action; | |
465 | ||
466 | GtkWidget *sigview = g_object_get_data(parent, "sigview"); | |
467 | sigview_zoom(sigview, 0, 0); | |
468 | } | |
469 | ||
470 | static const GtkActionEntry action_items[] = { | |
471 | /* name, stock-id, label, accel, tooltip, callback */ | |
472 | {"DevMenu", NULL, "_Device", NULL, NULL, NULL}, | |
473 | {"DevOpen", GTK_STOCK_OPEN, "_Open", "<control>O", | |
474 | "Open Session File", G_CALLBACK(dev_file_open)}, | |
475 | {"DevSelectMenu", NULL, "Select Device", NULL, NULL, NULL}, | |
476 | {"DevRescan", GTK_STOCK_REFRESH, "_Rescan", "<control>R", | |
477 | "Rescan for LA devices", G_CALLBACK(dev_select_rescan)}, | |
478 | {"DevProperties", GTK_STOCK_PROPERTIES, "_Properties", "<control>P", | |
479 | "Configure LA", G_CALLBACK(dev_set_options)}, | |
480 | {"DevProbes", GTK_STOCK_COLOR_PICKER, "_Probes", "<control>O", | |
481 | "Configure Probes", G_CALLBACK(dev_set_probes)}, | |
482 | {"DevAcquire", GTK_STOCK_EXECUTE, "_Acquire", "<control>A", | |
483 | "Acquire Samples", G_CALLBACK(capture_run)}, | |
484 | {"Exit", GTK_STOCK_QUIT, "E_xit", "<control>Q", | |
485 | "Exit the program", G_CALLBACK(gtk_main_quit) }, | |
486 | ||
487 | {"ViewMenu", NULL, "_View", NULL, NULL, NULL}, | |
488 | {"ViewZoomIn", GTK_STOCK_ZOOM_IN, "Zoom _In", "<control>z", NULL, | |
489 | G_CALLBACK(zoom_in)}, | |
490 | {"ViewZoomOut", GTK_STOCK_ZOOM_OUT, "Zoom _Out", "<control><shift>Z", | |
491 | NULL, G_CALLBACK(zoom_out)}, | |
492 | {"ViewZoomFit", GTK_STOCK_ZOOM_FIT, NULL, NULL, | |
493 | NULL, G_CALLBACK(zoom_fit)}, | |
494 | ||
495 | {"HelpMenu", NULL, "_Help", NULL, NULL, NULL}, | |
496 | {"HelpWiki", GTK_STOCK_ABOUT, "Sigrok _Wiki", NULL, NULL, | |
497 | G_CALLBACK(help_wiki)}, | |
498 | {"HelpAbout", GTK_STOCK_ABOUT, "_About", NULL, NULL, | |
499 | G_CALLBACK(help_about)}, | |
500 | }; | |
501 | ||
502 | static const GtkToggleActionEntry toggle_items[] = { | |
503 | /* name, stock-id, label, accel, tooltip, callback, isactive */ | |
504 | {"ViewLog", GTK_STOCK_JUSTIFY_LEFT, "_Log", NULL, NULL, | |
505 | G_CALLBACK(toggle_log), FALSE}, | |
506 | }; | |
507 | ||
508 | static const char ui_xml[] = | |
509 | "<ui>" | |
510 | " <menubar>" | |
511 | " <menu action='DevMenu'>" | |
512 | " <menuitem action='DevOpen'/>" | |
513 | " <separator/>" | |
514 | " <menu action='DevSelectMenu'>" | |
515 | " <separator/>" | |
516 | " <menuitem action='DevRescan'/>" | |
517 | " </menu>" | |
518 | " <menuitem action='DevProperties'/>" | |
519 | " <menuitem action='DevProbes'/>" | |
520 | " <separator/>" | |
521 | " <menuitem action='DevAcquire'/>" | |
522 | " <separator/>" | |
523 | " <menuitem action='Exit'/>" | |
524 | " </menu>" | |
525 | " <menu action='ViewMenu'>" | |
526 | " <menuitem action='ViewZoomIn'/>" | |
527 | " <menuitem action='ViewZoomOut'/>" | |
528 | " <menuitem action='ViewZoomFit'/>" | |
529 | " <separator/>" | |
530 | " <menuitem action='ViewLog'/>" | |
531 | " </menu>" | |
532 | " <menu action='HelpMenu'>" | |
533 | " <menuitem action='HelpWiki'/>" | |
534 | " <menuitem action='HelpAbout'/>" | |
535 | " </menu>" | |
536 | " </menubar>" | |
537 | " <toolbar>" | |
538 | " <placeholder name='DevSelect'/>" | |
539 | " <toolitem action='DevRescan'/>" | |
540 | " <toolitem action='DevProperties'/>" | |
541 | " <toolitem action='DevProbes'/>" | |
542 | " <separator/>" | |
543 | " <placeholder name='DevSampleCount' />" | |
544 | " <toolitem action='DevAcquire'/>" | |
545 | " <separator/>" | |
546 | " <toolitem action='ViewZoomIn'/>" | |
547 | " <toolitem action='ViewZoomOut'/>" | |
548 | " <toolitem action='ViewZoomFit'/>" | |
549 | " <separator/>" | |
550 | " </toolbar>" | |
551 | "</ui>"; | |
552 | ||
553 | GtkWidget *toolbar_init(GtkWindow *parent) | |
554 | { | |
555 | GtkWidget *vbox = gtk_vbox_new(FALSE, 0); | |
556 | GtkToolbar *toolbar; | |
557 | GtkActionGroup *ag = gtk_action_group_new("Actions"); | |
558 | gtk_action_group_add_actions(ag, action_items, | |
559 | G_N_ELEMENTS(action_items), parent); | |
560 | gtk_action_group_add_toggle_actions(ag, toggle_items, | |
561 | G_N_ELEMENTS(toggle_items), parent); | |
562 | ||
563 | GtkUIManager *ui = gtk_ui_manager_new(); | |
564 | g_object_set_data(G_OBJECT(parent), "ui_manager", ui); | |
565 | gtk_ui_manager_insert_action_group(ui, ag, 0); | |
566 | GtkAccelGroup *accel = gtk_ui_manager_get_accel_group(ui); | |
567 | gtk_window_add_accel_group(parent, accel); | |
568 | ||
569 | GError *error = NULL; | |
570 | if (!gtk_ui_manager_add_ui_from_string (ui, ui_xml, -1, &error)) { | |
571 | g_message ("building menus failed: %s", error->message); | |
572 | g_error_free (error); | |
573 | exit (-1); | |
574 | } | |
575 | ||
576 | GtkWidget *menubar = gtk_ui_manager_get_widget(ui, "/menubar"); | |
577 | gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(menubar), FALSE, TRUE, 0); | |
578 | toolbar = GTK_TOOLBAR(gtk_ui_manager_get_widget(ui, "/toolbar")); | |
579 | gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(toolbar), FALSE, TRUE, 0); | |
580 | ||
581 | /* Device selection GtkComboBox */ | |
582 | GtkToolItem *toolitem = gtk_tool_item_new(); | |
583 | GtkWidget *align = gtk_alignment_new(0.5, 0.5, 2, 0); | |
584 | GtkWidget *dev = dev_select_combo_box_new(parent); | |
585 | ||
586 | gtk_container_add(GTK_CONTAINER(align), dev); | |
587 | gtk_container_add(GTK_CONTAINER(toolitem), align); | |
588 | gtk_toolbar_insert(toolbar, toolitem, 0); | |
589 | ||
590 | /* Time/Samples entry */ | |
591 | toolitem = gtk_tool_item_new(); | |
592 | GtkWidget *timesamples = gtk_entry_new(); | |
593 | gtk_entry_set_text(GTK_ENTRY(timesamples), "100"); | |
594 | gtk_entry_set_alignment(GTK_ENTRY(timesamples), 1.0); | |
595 | gtk_widget_set_size_request(timesamples, 100, -1); | |
596 | gtk_container_add(GTK_CONTAINER(toolitem), timesamples); | |
597 | gtk_toolbar_insert(toolbar, toolitem, 7); | |
598 | ||
599 | /* Time unit combo box */ | |
600 | toolitem = gtk_tool_item_new(); | |
601 | align = gtk_alignment_new(0.5, 0.5, 2, 0); | |
602 | GtkWidget *timeunit = gtk_combo_box_new_text(); | |
603 | gtk_combo_box_append_text(GTK_COMBO_BOX(timeunit), "samples"); | |
604 | gtk_combo_box_append_text(GTK_COMBO_BOX(timeunit), "ms"); | |
605 | gtk_combo_box_append_text(GTK_COMBO_BOX(timeunit), "s"); | |
606 | gtk_combo_box_set_active(GTK_COMBO_BOX(timeunit), 0); | |
607 | gtk_container_add(GTK_CONTAINER(align), timeunit); | |
608 | gtk_container_add(GTK_CONTAINER(toolitem), align); | |
609 | gtk_toolbar_insert(toolbar, toolitem, 8); | |
610 | ||
611 | g_object_set_data(G_OBJECT(parent), "timesamples", timesamples); | |
612 | g_object_set_data(G_OBJECT(parent), "timeunit", timeunit); | |
613 | ||
614 | return GTK_WIDGET(vbox); | |
615 | } | |
616 |