1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 Grig: Gtk+ user interface for the Hamradio Control Libraries.
4
5 Copyright (C) 2001-2007 Alexandru Csete.
6
7 Authors: Alexandru Csete <oz9aec@gmail.com>
8
9 Comments, questions and bugreports should be submitted via
10 http://sourceforge.net/projects/groundstation/
11 More details can be found at the project home page:
12
13 http://groundstation.sourceforge.net/
14
15 This program is free software; you can redistribute it and/or modify
16 it under the terms of the GNU General Public License as published by
17 the Free Software Foundation; either version 2 of the License, or
18 (at your option) any later version.
19
20 This program is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU General Public License for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with this program; if not, visit http://www.fsf.org/
27
28
29
30
31 */
32 #include <gtk/gtk.h>
33 #include <hamlib/rig.h>
34 #include <glib/gi18n.h>
35 #include "rig-data.h"
36 #include "rig-utils.h"
37 #include "grig-gtk-workarounds.h"
38 #include "grig-debug.h"
39 #include "rig-gui-vfo.h"
40
41
42
43
44
45 /* private function prototypes */
46
47 /* VFO frame */
48 static GtkWidget *rig_gui_vfo_create_toggle (void);
49 static GtkWidget *rig_gui_vfo_create_eq_button (void);
50 static GtkWidget *rig_gui_vfo_create_xchg_button (void);
51 static GtkWidget *rig_gui_vfo_create_split_button (void);
52 static GtkWidget *rig_gui_vfo_create_mem_button (void);
53
54 static void rig_gui_vfo_toggle_cb (GtkWidget *, gpointer);
55 static void rig_gui_vfo_eq_cb (GtkWidget *, gpointer);
56 static void rig_gui_vfo_xchg_cb (GtkWidget *, gpointer);
57 static void rig_gui_vfo_split_cb (GtkWidget *, gpointer);
58 static void rig_gui_vfo_memory_cb (GtkWidget *, gpointer);
59
60 /* MEM Frame */
61
62
63 /* Band frame */
64
65
66 /** \brief Create VFO operation controls.
67 * \return a composite widget containing the controls.
68 *
69 */
70 GtkWidget *
rig_gui_vfo_create()71 rig_gui_vfo_create ()
72 {
73 /* GtkWidget *hbox;
74 GtkWidget *vfobox;
75 GtkWidget *bandbox;
76 */
77 GtkWidget *grid;
78
79 /* VFO Frame */
80 /* vfobox = gtk_vbutton_box_new ();
81 gtk_button_box_set_layout (GTK_BUTTON_BOX (vfobox), GTK_BUTTONBOX_START);
82 gtk_container_add (GTK_CONTAINER (vfobox), rig_gui_vfo_create_toggle ());
83 gtk_container_add (GTK_CONTAINER (vfobox), rig_gui_vfo_create_split_button ());
84 gtk_container_add (GTK_CONTAINER (vfobox), rig_gui_vfo_create_eq_button ());
85 gtk_container_add (GTK_CONTAINER (vfobox), rig_gui_vfo_create_xchg_button ());*/
86
87 grid = gtk_table_new (4, 3, TRUE);
88 gtk_table_attach_defaults (GTK_TABLE (grid), rig_gui_vfo_create_toggle (), 0, 1, 0, 1);
89 gtk_table_attach_defaults (GTK_TABLE (grid), rig_gui_vfo_create_split_button (), 1, 2, 0, 1);
90 gtk_table_attach_defaults (GTK_TABLE (grid), rig_gui_vfo_create_eq_button (), 0, 1, 1, 2);
91 gtk_table_attach_defaults (GTK_TABLE (grid), rig_gui_vfo_create_xchg_button (), 1, 2, 1, 2);
92 gtk_table_attach_defaults (GTK_TABLE (grid), rig_gui_vfo_create_mem_button (), 0, 1, 2, 3);
93
94 /* BAND UP/DOWN */
95 /* XXX not yet implemented */
96 /*
97 bandbox = gtk_hbutton_box_new ();
98 gtk_button_box_set_layout (GTK_BUTTON_BOX (bandbox), GTK_BUTTONBOX_END);
99 */
100 return grid;
101 }
102
103
104 /**** A/B button ****/
105
106
107 static GtkWidget *
rig_gui_vfo_create_toggle()108 rig_gui_vfo_create_toggle ()
109 {
110 GtkWidget *button;
111 gint vfos;
112
113 /* Create button widget.
114 The label will be "A/B" if the rig has VFO_A and VFO_B
115 or Main/Sub if the rig has those two.
116 */
117 vfos = rig_data_get_vfos ();
118 if (vfos & RIG_VFO_MAIN) {
119 button = gtk_button_new_with_label (_("Main / Sub"));
120 gtk_widget_set_tooltip_text (button, _("Toggle active VFO"));
121 }
122 else {
123 button = gtk_button_new_with_label (_("A / B"));
124 gtk_widget_set_tooltip_text (button, _("Toggle between available VFOs"));
125 }
126
127
128 /* Disable control if the rig has no capability of
129 either setting a specific VFO or to toggle
130 */
131 if (!(rig_data_has_vfo_op_toggle () ||
132 (rig_data_has_set_vfo () && rig_data_has_get_vfo ())) ){
133 gtk_widget_set_sensitive (button, FALSE);
134 }
135
136
137 /* connect "toggle" signal */
138 g_signal_connect (G_OBJECT (button), "pressed",
139 G_CALLBACK (rig_gui_vfo_toggle_cb),
140 NULL);
141
142
143 return button;
144 }
145
146
147
148
149 static void
rig_gui_vfo_toggle_cb(GtkWidget * widget,gpointer data)150 rig_gui_vfo_toggle_cb (GtkWidget *widget, gpointer data)
151 {
152
153 if (rig_data_has_vfo_op_toggle ()) {
154 rig_data_vfo_op_toggle ();
155 }
156 else if (rig_data_has_set_vfo () &&
157 rig_data_has_get_vfo ()) {
158
159 /* do not toggle in memory mode */
160 /* XXX disable other VFO buttons? */
161 if (rig_data_get_vfo() == RIG_VFO_MEM)
162 return;
163
164 /* do we have VFO A and B? */
165 if (rig_data_get_vfos() & (RIG_VFO_A | RIG_VFO_B)) {
166
167 if (rig_data_get_vfo () == RIG_VFO_A) {
168 rig_data_set_vfo (RIG_VFO_B);
169 }
170 else {
171 rig_data_set_vfo (RIG_VFO_A);
172 }
173
174 }
175 /* else try MAIN/SUB */
176 else if (rig_data_get_vfos () & (RIG_VFO_MAIN | RIG_VFO_SUB)) {
177
178 if (rig_data_get_vfo () == RIG_VFO_MAIN) {
179 rig_data_set_vfo (RIG_VFO_SUB);
180 }
181 else {
182 rig_data_set_vfo (RIG_VFO_MAIN);
183 }
184 }
185
186 /* it's a bug, because button should be disabled */
187 else {
188 grig_debug_local (RIG_DEBUG_BUG,
189 "%s: VFO_TOGGLE button should have been disabled "\
190 "(neither A/B nor MAIN/SUB)\n", __FUNCTION__);
191 }
192 }
193
194 /* it's a bug, because button should be disabled */
195 else {
196 grig_debug_local (RIG_DEBUG_BUG,
197 "%s: VFO_TOGGLE button should have been disabled "\
198 "(no way to toggle)\n", __FUNCTION__);
199 }
200
201 }
202
203 static void
rig_gui_vfo_memory_cb(GtkWidget * widget,gpointer data)204 rig_gui_vfo_memory_cb(GtkWidget *widget, gpointer data)
205 {
206 if (rig_data_has_set_vfo() && rig_data_has_get_vfo()) {
207
208 if (rig_data_get_vfo() != RIG_VFO_MEM) {
209 g_object_set_data(G_OBJECT(widget),
210 "vfo", (gpointer) rig_data_get_vfo());
211
212 rig_data_set_vfo(RIG_VFO_MEM);
213
214 } else {
215 rig_data_set_vfo((vfo_t) g_object_get_data(G_OBJECT(widget),
216 "vfo"));
217 }
218 }
219 }
220
221 /**** A=B button ****/
222
223 static GtkWidget *
rig_gui_vfo_create_eq_button()224 rig_gui_vfo_create_eq_button ()
225 {
226 GtkWidget *button;
227 gint vfos;
228
229 /* Create button widget.
230 The label will be "A=B" if the rig has VFO_A and VFO_B
231 or Main=Sub if the rig has those two.
232 */
233 vfos = rig_data_get_vfos ();
234 if (vfos & RIG_VFO_MAIN) {
235 button = gtk_button_new_with_label (_("Main = Sub"));
236 gtk_widget_set_tooltip_text (button,_("Set Main VFO = Sub VFO"));
237 }
238 else {
239 button = gtk_button_new_with_label (_("A = B"));
240 gtk_widget_set_tooltip_text (button, _("Set VFO B = VFO A"));
241 }
242 /* Disable control if the rig has no capability of
243 either setting a specific VFO or to toggle
244 */
245 if (!(rig_data_has_vfo_op_toggle () ||
246 (rig_data_has_set_vfo () && rig_data_has_get_vfo ())) ){
247 gtk_widget_set_sensitive (button, FALSE);
248 }
249
250
251 /* connect "toggle" signal */
252 g_signal_connect (G_OBJECT (button), "pressed",
253 G_CALLBACK (rig_gui_vfo_eq_cb),
254 NULL);
255
256
257 return button;
258 }
259
260
261
262
263 static void
rig_gui_vfo_eq_cb(GtkWidget * widget,gpointer data)264 rig_gui_vfo_eq_cb (GtkWidget *widget, gpointer data)
265 {
266
267 if (rig_data_has_vfo_op_copy ()) {
268 rig_data_vfo_op_copy ();
269 }
270 else if (rig_data_has_set_vfo () &&
271 rig_data_has_get_vfo ()) {
272
273 grig_debug_local (RIG_DEBUG_BUG,
274 "%s: VFO COPY without RIG_OP_COPY not imlemented\n",
275 __FUNCTION__);
276
277 }
278
279 /* it's a bug, because button should be disabled */
280 else {
281 grig_debug_local (RIG_DEBUG_BUG,
282 "%s: VFO_EQ button should have been disabled "\
283 "(no way to equalise)\n", __FUNCTION__);
284 }
285
286 }
287
288
289
290 /**** A<->B button ****/
291
292 static GtkWidget *
rig_gui_vfo_create_xchg_button()293 rig_gui_vfo_create_xchg_button ()
294 {
295 GtkWidget *button;
296 gint vfos;
297
298 /* Create button widget.
299 The label will be "A<->B" if the rig has VFO_A and VFO_B
300 or Main<->Sub if the rig has those two.
301 */
302 vfos = rig_data_get_vfos ();
303 if (vfos & RIG_VFO_MAIN) {
304 button = gtk_button_new_with_label (_("Main\302\253\302\273Sub"));
305 gtk_widget_set_tooltip_text (button, _("Exchange Main and sub VFOs"));
306 }
307 else {
308 button = gtk_button_new_with_label (_("A\302\253\302\273B"));
309 gtk_widget_set_tooltip_text (button, _("Exchange VFO A and B"));
310 }
311
312
313 /* Disable control if the rig has no capability of
314 either setting a specific VFO or to toggle
315 */
316 if (!(rig_data_has_vfo_op_xchg () ||
317 (rig_data_has_set_vfo () && rig_data_has_get_vfo ())) ){
318 gtk_widget_set_sensitive (button, FALSE);
319 }
320
321
322 /* connect "toggle" signal */
323 g_signal_connect (G_OBJECT (button), "pressed",
324 G_CALLBACK (rig_gui_vfo_xchg_cb),
325 NULL);
326
327
328 return button;
329 }
330
331
332
333
334 static void
rig_gui_vfo_xchg_cb(GtkWidget * widget,gpointer data)335 rig_gui_vfo_xchg_cb (GtkWidget *widget, gpointer data)
336 {
337
338 if (rig_data_has_vfo_op_xchg ()) {
339 rig_data_vfo_op_xchg ();
340 }
341 else if (rig_data_has_set_vfo () &&
342 rig_data_has_get_vfo ()) {
343
344 grig_debug_local (RIG_DEBUG_BUG,
345 "%s: VFO XCHG without RIG_OP_XCHG not imlemented\n",
346 __FUNCTION__);
347
348 }
349
350 /* it's a bug, because button should be disabled */
351 else {
352 grig_debug_local (RIG_DEBUG_BUG,
353 "%s: VFO_XCHG button should have been disabled "\
354 "(no way to exchange)\n", __FUNCTION__);
355 }
356
357 }
358
359
360
361
362 /**** SPLIT button ****/
363 /** FIXME: need readback from RIG **/
364 static GtkWidget *
rig_gui_vfo_create_split_button()365 rig_gui_vfo_create_split_button ()
366 {
367 GtkWidget *button;
368
369
370 button = gtk_toggle_button_new_with_label (_("Split"));
371 gtk_widget_set_tooltip_text (button, _("Toggle split mode operation"));
372
373 /* set button status before we do anything else */
374 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
375 rig_data_get_split ());
376
377 /* Disable control if the rig has no capability of
378 either setting a specific VFO or to toggle
379 */
380 if (!(rig_data_has_set_split ())) {
381 gtk_widget_set_sensitive (button, FALSE);
382 }
383
384
385 /* connect "toggle" signal */
386 g_signal_connect (G_OBJECT (button), "toggled",
387 G_CALLBACK (rig_gui_vfo_split_cb),
388 NULL);
389
390
391 return button;
392 }
393
394 static GtkWidget *
rig_gui_vfo_create_mem_button()395 rig_gui_vfo_create_mem_button()
396 {
397 GtkWidget *button;
398
399 button = gtk_button_new_with_label(_("M / V"));
400 gtk_widget_set_tooltip_text (button, _("Toggle between memory and VFO"));
401
402 /* Disable control if the rig has no memory vfo */
403 if (!(rig_data_get_vfos() & RIG_VFO_MEM)) {
404 gtk_widget_set_sensitive(button, FALSE);
405 }
406
407 g_object_set_data(G_OBJECT(button), "vfo", (gpointer) RIG_VFO_VFO);
408
409 g_signal_connect(G_OBJECT (button), "pressed",
410 G_CALLBACK (rig_gui_vfo_memory_cb), NULL);
411 return button;
412 }
413
414 static void
rig_gui_vfo_split_cb(GtkWidget * widget,gpointer data)415 rig_gui_vfo_split_cb (GtkWidget *widget, gpointer data)
416 {
417 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) {
418 rig_data_set_split (TRUE);
419 }
420 else {
421 rig_data_set_split (FALSE);
422 }
423 }
424