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