1 #ifdef HAVE_CONFIG_H
2 #  include <config.h>
3 #endif
4 
5 #include <gtk/gtk.h>
6 #include <string.h>
7 #include <libintl.h>
8 
9 #include "callbacks.h"
10 #include "interface.h"
11 #include "support.h"
12 #include "configlib.h"
13 #include "main.h"
14 
15 extern GtkWidget *mainWindow;
16 
17 void
on_nouveau_activate(GtkMenuItem * menuitem,gpointer user_data)18 on_nouveau_activate                   (GtkMenuItem     *menuitem,
19                                        gpointer         user_data)
20 {
21   GtkWidget *dialog;
22   gint retour;
23 
24   dialog = GTK_WIDGET(create_newConfirmDialog());
25   retour = gtk_dialog_run(GTK_DIALOG(dialog));
26 
27   switch(retour)
28   {
29     case GTK_RESPONSE_ACCEPT:
30       newConfig();
31       break;
32 
33     case GTK_RESPONSE_CANCEL:
34       break;
35   }
36 
37   gtk_widget_destroy(dialog);
38 }
39 
40 
41 void
on_ouvrir_activate(GtkMenuItem * menuitem,gpointer user_data)42 on_ouvrir_activate                    (GtkMenuItem     *menuitem,
43                                         gpointer         user_data)
44 {
45   GtkWidget *dialog;
46   gint retour;
47   gchar *filename, *tmp;
48   config_t *conf;
49 
50   dialog = gtk_file_chooser_dialog_new(
51               gettext("Open new configuration"),
52               GTK_WINDOW(mainWindow),
53               GTK_FILE_CHOOSER_ACTION_OPEN,
54               GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
55               GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
56               NULL);
57 
58   retour = gtk_dialog_run(GTK_DIALOG(dialog));
59   switch(retour)
60   {
61     case GTK_RESPONSE_ACCEPT:
62       filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
63       if (filename == NULL)
64       {
65         ErrorBox(mainWindow,
66                  gettext("No config file specified.\n"
67                          "Internal Error, aborting.\n")
68         );
69         break;
70       }
71 
72       conf = parseConfig(filename);
73       if (! conf)
74       {
75         ErrorBox(mainWindow,
76                  gettext("Error parsing config file.\n"
77                          "Aborting.\n")
78         );
79         break;
80       }
81 
82       g_object_set_data(G_OBJECT(mainWindow), "_conf_filename", filename);
83       if (! setConfig(conf, mainWindow))
84       {
85         ErrorBox(mainWindow,
86                  gettext("Configuration file is invalid.\n"
87                          "Aborting.\n")
88         );
89         g_object_set_data(G_OBJECT(mainWindow), "_conf_filename", NULL);
90         g_free(filename);
91       }
92       _conf_freeConfig( conf ); /* Avoid leak ;) */
93       break;
94 
95     case GTK_RESPONSE_CANCEL:
96       break;
97 
98   }
99 
100   gtk_widget_destroy(dialog);
101 }
102 
103 
104 gboolean
on_enregistrer_activate(GtkMenuItem * menuitem,gpointer user_data)105 on_enregistrer_activate               (GtkMenuItem     *menuitem,
106                                         gpointer         user_data)
107 {
108   GtkWidget *main, *dialog;
109   gchar *filename;
110   gboolean retval = FALSE;
111   config_t *conf;
112   FILE *configFile;
113 
114   main = mainWindow;
115   if ( (filename = g_object_get_data(G_OBJECT(main), "_conf_filename")) != NULL)
116   {
117     conf = buildConfig();
118     if (conf ==  NULL)
119     {
120       ErrorBox(main, gettext("An error was detected during the configuration building.\n"
121                              "Settings are not acceptable. Please reconfigure cPige.\n"
122                              "This would happens for example if you've not added an URL.\n")
123       );
124     } else {
125       if ( (configFile = (FILE *)g_fopen(filename, "w")) == NULL)
126       {
127         ErrorBox(main,
128             gettext("Unable to open your config file for writing.\n"
129                     "Please verify rights.\n")
130         );
131       } else {
132         g_object_set_data(G_OBJECT(main), "_conf_filename", filename);
133         _conf_writeConfig( configFile , conf );
134         _conf_freeConfig( conf );
135         fclose(configFile);
136         retval = TRUE;
137       }
138     }
139   } else
140     return on_enregistrer_sous_activate(NULL, user_data);
141 
142   return retval;
143 }
144 
145 
146 gboolean
on_enregistrer_sous_activate(GtkMenuItem * menuitem,gpointer user_data)147 on_enregistrer_sous_activate          (GtkMenuItem     *menuitem,
148                                         gpointer         user_data)
149 {
150   GtkWidget *saveDialog;
151   GtkWidget *dialog;
152   GtkWidget *main;
153   gint retour;
154   gboolean retval = FALSE;
155   gchar *filename;
156   FILE *configFile;
157   config_t *conf;
158 
159   main = mainWindow;
160   conf = buildConfig();
161   if (conf ==  NULL)
162   {
163     ErrorBox(main,
164              gettext("An error was detected during the configuration building.\n"
165                      "Settings are not acceptable. Please reconfigure cPige.\n"
166                      "This would happens for example if you've not added an URL.\n")
167     );
168     return;
169   }
170 
171   saveDialog = GTK_WIDGET(create_FileSaveDialog());
172   retour = gtk_dialog_run(GTK_DIALOG(saveDialog));
173   switch (retour)
174   {
175     case GTK_RESPONSE_OK:
176     case GTK_RESPONSE_ACCEPT:
177       filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(saveDialog));
178       if ( (configFile = (FILE *)g_fopen(filename, "w")) == NULL)
179       {
180         gtk_widget_destroy(GTK_WIDGET(saveDialog));
181         ErrorBox(
182             main,
183             gettext("Unable to open config file for writing.\nSettings will *NOT* be saved.\n")
184         );
185       } else {
186         g_object_set_data(G_OBJECT(main), "_conf_filename", strdup(filename));
187         gtk_widget_destroy(GTK_WIDGET(saveDialog));
188         _conf_writeConfig( configFile, conf );
189         fclose(configFile);
190         retval = TRUE;
191       }
192 
193       g_free(filename);
194       break;
195 
196     case GTK_RESPONSE_CANCEL:
197     default:
198       gtk_widget_destroy(GTK_WIDGET(saveDialog));
199       break;
200   }
201 
202   _conf_freeConfig( conf );
203 
204   return retval;
205 }
206 
207 
208 void
on_quitter_activate(GtkMenuItem * menuitem,gpointer user_data)209 on_quitter_activate                   (GtkMenuItem     *menuitem,
210                                         gpointer         user_data)
211 {
212   GtkWidget *dialog;
213   gint ret;
214   gint is_quit = 1;
215 
216   if (is_cpige_running())
217   {
218     dialog = gtk_message_dialog_new(
219         GTK_WINDOW(mainWindow),
220         GTK_DIALOG_DESTROY_WITH_PARENT,
221         GTK_MESSAGE_QUESTION,
222         GTK_BUTTONS_YES_NO,
223         gettext("Warning, cPige is currently recording.\n"
224                 "Exiting will shutdown cPige.\n"
225                 "Do you really want to continue ?\n")
226     );
227 
228     ret = gtk_dialog_run(GTK_DIALOG(dialog));
229     switch(ret)
230     {
231       case GTK_RESPONSE_YES:
232         kill_cpige();
233         break;
234 
235       case GTK_RESPONSE_NO:
236       default:
237         is_quit = 0;
238         break;
239     }
240     gtk_widget_destroy(GTK_WIDGET(dialog));
241   }
242 
243   if (is_quit)
244     exit(0);
245 }
246 
247 void
on_AddUrlBUtton_pressed(GtkButton * button,gpointer user_data)248 on_AddUrlBUtton_pressed                (GtkButton       *button,
249                                         gpointer         user_data)
250 {
251   GtkTreeView *URLTree;
252   GtkDialog *addurlDialog;
253   GtkEntry *urlEntry;
254   gint retour;
255 
256   addurlDialog = GTK_DIALOG(create_URLAddDialog());
257 
258   retour = gtk_dialog_run(addurlDialog);
259   switch (retour)
260   {
261     case GTK_RESPONSE_OK:
262       URLTree = GTK_TREE_VIEW(lookup_widget(GTK_WIDGET(button), "URLTreeView"));
263       urlEntry = GTK_ENTRY(lookup_widget(GTK_WIDGET(addurlDialog), "URLAddEntry"));
264       addURL(URLTree, (gchar *)gtk_entry_get_text(urlEntry));
265       something_changed(NULL, NULL);
266       break;
267     default:
268       /* No action */
269       break;
270   }
271   gtk_widget_destroy(GTK_WIDGET(addurlDialog));
272 }
273 
274 void
on_DelURLButton_pressed(GtkButton * button,gpointer user_data)275 on_DelURLButton_pressed                (GtkButton       *button,
276                                         gpointer         user_data)
277 {
278   GtkTreeView *URLTree;
279   GtkTreeSelection *Selection;
280   GtkTreeIter iter;
281   GtkListStore *ListStore;
282 
283   URLTree = (GtkTreeView *)lookup_widget((GtkWidget *)button, "URLTreeView");
284   ListStore = GTK_LIST_STORE(gtk_tree_view_get_model(URLTree));
285   if (! ListStore)
286   {
287     g_printf("No valid ListStore found. Could not remove an item.\n");
288     return;
289   }
290 
291   Selection = gtk_tree_view_get_selection(URLTree);
292 
293   if (gtk_tree_selection_get_selected (Selection,
294                                    NULL,
295                                    &iter))
296     gtk_list_store_remove(ListStore, &iter);
297 
298   something_changed(NULL, NULL);
299 }
300 
301 void
on_IntervalTypeComboBox_changed(GtkComboBox * combobox,gpointer user_data)302 on_IntervalTypeComboBox_changed        (GtkComboBox     *combobox,
303                                         gpointer         user_data)
304 {
305   gint idx;
306   GtkSpinButton *spinButton;
307 
308   spinButton = GTK_SPIN_BUTTON(lookup_widget(GTK_WIDGET(combobox), "IntervalDelaySpinButton"));
309 
310   idx = gtk_combo_box_get_active(combobox);
311   if (idx == 0) /* Hour */
312   {
313     gtk_spin_button_set_adjustment(spinButton, GTK_ADJUSTMENT(gtk_adjustment_new (1, 1, 12, 1, 1, 1)));
314     gtk_spin_button_set_value(spinButton, 1);
315   } else if (idx == 1) { /* Minute */
316     gtk_spin_button_set_adjustment(spinButton, GTK_ADJUSTMENT(gtk_adjustment_new (10, 10, 30, 10, 10, 10)));
317     gtk_spin_button_set_value(spinButton, 10);
318   } else {
319     g_printf("Unknown interval type (%d)\n", idx);
320   }
321 }
322 
323 
324 void
on_pigeModeButton_pressed(GtkButton * button,gpointer user_data)325 on_pigeModeButton_pressed              (GtkButton       *button,
326                                         gpointer         user_data)
327 {
328   GtkFrame *PigeFrame;
329   GtkToggleButton *weekbackup, *useNumbers, *pigeMetaButton;
330   gboolean state;
331 
332   PigeFrame      = GTK_FRAME(lookup_widget(GTK_WIDGET(button), "PigeModeFrame"));
333 
334   weekbackup     = GTK_TOGGLE_BUTTON(lookup_widget(GTK_WIDGET(button), "WeekBackupButton"));
335   useNumbers     = GTK_TOGGLE_BUTTON(lookup_widget(GTK_WIDGET(button), "useNumbersButton"));
336   pigeMetaButton = GTK_TOGGLE_BUTTON(lookup_widget(GTK_WIDGET(button), "pigeMetaButton"));
337 
338   state = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button));
339   if (state == FALSE) /* Button *was* active. */
340   {
341     gtk_widget_set_sensitive(GTK_WIDGET(PigeFrame),      FALSE);
342     gtk_widget_set_sensitive(GTK_WIDGET(useNumbers),     TRUE);
343     gtk_widget_set_sensitive(GTK_WIDGET(weekbackup),     FALSE);
344     gtk_widget_set_sensitive(GTK_WIDGET(pigeMetaButton), FALSE);
345   }
346   else /* Button *was* inactive */
347   {
348     gtk_widget_set_sensitive(GTK_WIDGET(PigeFrame),      TRUE);
349     gtk_widget_set_sensitive(GTK_WIDGET(useNumbers),     FALSE);
350     gtk_widget_set_sensitive(GTK_WIDGET(weekbackup),     TRUE);
351     gtk_widget_set_sensitive(GTK_WIDGET(pigeMetaButton), TRUE);
352   }
353 }
354 
355 
356 void
on_startButton_clicked(GtkButton * button,gpointer user_data)357 on_startButton_clicked                 (GtkButton       *button,
358                                         gpointer         user_data)
359 {
360   gboolean state;
361   GtkWidget *image;
362   GtkWidget *wid;
363   GtkWidget *main;
364   int i;
365   gchar *DisableFrames[] = {"ParametersFrame", "ExtraParametersFrame", NULL};
366   gchar *iter, *filename;
367 
368   main = mainWindow;
369 
370   if ( (filename = g_object_get_data(G_OBJECT(main), "_conf_filename")) == NULL)
371   {
372     if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)))
373       WarningBox( main,
374                   gettext("You must save your configuration before launching cPige.\n")
375       );
376 
377     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), FALSE);
378     return;
379   }
380 
381   state = (gboolean)g_object_get_data(G_OBJECT(button), "savemode");
382   if ((state == TRUE) &&
383       (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)) == TRUE))
384   {
385     if (on_enregistrer_activate(NULL, user_data) == TRUE)
386     {
387       gtk_button_set_label(button, gettext("Start"));
388       g_object_set_data(G_OBJECT(button), "savemode", FALSE);
389     }
390     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), FALSE);
391     return;
392   }
393 
394   image = lookup_widget(GTK_WIDGET(button), "startButtonImage");
395   state = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button));
396 
397   if (state == TRUE)
398   {
399     if (! launch_cpige())
400     {
401       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), FALSE);
402       return;
403     }
404 
405     gtk_button_set_label(button, gettext("Stop"));
406     /* Icon gtk-stop */
407     gtk_image_set_from_stock(GTK_IMAGE(image), GTK_STOCK_QUIT, GTK_ICON_SIZE_BUTTON);
408   } else {
409     gtk_button_set_label(button, gettext("Start"));
410     /* Icon gtk-media-play */
411     gtk_image_set_from_stock(GTK_IMAGE(image), GTK_STOCK_MEDIA_PLAY, GTK_ICON_SIZE_BUTTON);
412     g_object_set_data(G_OBJECT(mainWindow), "stopping", (void *)NULL);
413     kill_cpige();
414   }
415   gtk_button_set_image(button, image);
416 
417   for (i = 0; DisableFrames[i] != NULL; i++)
418   {
419     wid = lookup_widget(GTK_WIDGET(button), DisableFrames[i]);
420     gtk_widget_set_sensitive(wid, !state);
421   }
422 }
423 
424 void
on_LogfileCheckButton_pressed(GtkButton * button,gpointer user_data)425 on_LogfileCheckButton_pressed          (GtkButton       *button,
426                                         gpointer         user_data)
427 {
428   GtkWidget *lbutton, *entry;
429   gboolean state;
430 
431   lbutton = lookup_widget(GTK_WIDGET(button), "LogfileChooserButton");
432   entry = lookup_widget(GTK_WIDGET(button), "LogfileEntry");
433   state = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button));
434   if (state == FALSE) /* The button was active, and is not inactive */
435   {
436     gtk_widget_set_sensitive(lbutton, FALSE);
437     gtk_widget_set_sensitive(entry, FALSE);
438   } else { /* The button was inactive and is now active */
439     gtk_widget_set_sensitive(lbutton, TRUE);
440     gtk_widget_set_sensitive(entry, TRUE);
441   }
442 
443   something_changed(NULL, NULL);
444 }
445 
446 void
on_log_open_pressed(GtkButton * button,gpointer user_data)447 on_log_open_pressed                    (GtkButton       *button,
448                                         gpointer         user_data)
449 {
450   GtkWidget *saveDialog;
451   GtkWidget *logentry;
452   gint retour;
453   gchar *filename;
454   FILE *logFile;
455 
456   saveDialog = GTK_WIDGET(create_FileSaveDialog());
457   retour = gtk_dialog_run(GTK_DIALOG(saveDialog));
458   switch (retour)
459   {
460     case GTK_RESPONSE_OK:
461     case GTK_RESPONSE_ACCEPT:
462       filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(saveDialog));
463       if ( (logFile = (FILE *)g_fopen(filename, "w")) == NULL)
464       {
465         gtk_widget_destroy(GTK_WIDGET(saveDialog));
466         ErrorBox(
467             mainWindow,
468             gettext("Unable to open config file for writing.\nSettings will *NOT* be saved.\n")
469         );
470       } else {
471         gtk_widget_destroy(GTK_WIDGET(saveDialog));
472         logentry = lookup_widget(GTK_WIDGET(button), "LogfileEntry");
473         gtk_entry_set_text(GTK_ENTRY(logentry), filename);
474         something_changed(NULL, NULL);
475         fclose(logFile);
476       }
477 
478       g_free(filename);
479       break;
480 
481     case GTK_RESPONSE_CANCEL:
482     default:
483       gtk_widget_destroy(GTK_WIDGET(saveDialog));
484       break;
485   }
486 
487 }
488 
489 
490 void
url_edited_callback(GtkCellRendererText * cell,gchar * path_string,gchar * new_text,gpointer model)491 url_edited_callback                    (GtkCellRendererText *cell,
492                                         gchar               *path_string,
493                                         gchar               *new_text,
494                                         gpointer            model)
495 {
496   GtkTreeIter iter;
497 
498   if (gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(model), &iter, path_string) == FALSE)
499   {
500     g_printf("Edited wrong cell!!\n");
501     return;
502   }
503 
504   gtk_list_store_set(model, &iter, 0, new_text, -1);
505   something_changed(NULL, NULL);
506 }
507 
something_changed(GtkButton * button,gpointer user_data)508 void something_changed(GtkButton       *button,
509                        gpointer         user_data)
510 {
511   gint state;
512   GtkWidget *startButton;
513   /* Something in the configuration has changed.
514    *
515    * cPige GUI will change the Start Button
516    * to Save / Start
517    */
518 
519   /* Retreive start button state */
520   startButton = lookup_widget(GTK_WIDGET(mainWindow), "startButton");
521 
522   state = (gboolean)g_object_get_data(G_OBJECT(startButton), "savemode");
523   if (state == 0)
524   {
525     /* Button is not in save mode. Switch to save mode ;) */
526     g_object_set_data(G_OBJECT(startButton), "savemode", (gpointer)TRUE);
527     gtk_button_set_label(GTK_BUTTON(startButton), gettext("Apply"));
528   }
529 }
530 
531 
532 /* GIOFunc */
cPigeEvent(GIOChannel * source,GIOCondition condition,gpointer data)533 gboolean cPigeEvent (GIOChannel *source,
534                      GIOCondition condition,
535                      gpointer data)
536 {
537   GError *error = NULL;
538   GtkWidget *titleWidget, *nextTitleWidget;
539   GtkWidget *progress;
540   GtkWidget *startButton;
541   gchar *line;
542   gsize line_len, terminator;
543   gchar *title;
544   gchar *next_title;
545   gchar *left;
546   gchar *percent_str;
547   if ((condition & G_IO_IN) || (condition & G_IO_PRI))
548   {
549     /* Lookup widget to update */
550     titleWidget     = lookup_widget(GTK_WIDGET(mainWindow), "titleEntry");
551     nextTitleWidget = lookup_widget(GTK_WIDGET(mainWindow), "nexttitleEntry");
552     progress        = lookup_widget(GTK_WIDGET(mainWindow), "timeleftProgressBar");
553 
554     /* there is data to read */
555     if (g_io_channel_read_line(source, &line, &line_len, &terminator, &error) != G_IO_STATUS_NORMAL)
556     {
557       g_warning("Error reading the line ...\n");
558       gtk_entry_set_text(GTK_ENTRY(titleWidget),     "");
559       gtk_entry_set_text(GTK_ENTRY(nextTitleWidget), "");
560       gtk_progress_set_percentage(GTK_PROGRESS(progress), 0.0);
561       gtk_progress_bar_set_text(GTK_PROGRESS_BAR(progress), "timeleft");
562       return FALSE;
563     }
564 
565     line[terminator] = '\0';
566 
567     if ((line_len < 9) || (strncmp((char *)line, "CPIGEGUI", 8) != 0))
568     {
569       g_free(line);
570       return TRUE;
571     }
572 
573     line += 9;
574     line_len -= 9;
575 
576     title       = (gchar *)strtok(line, ":");
577     next_title  = (gchar *)strtok(NULL, ":");
578     left        = (gchar *)strtok(NULL, ":");
579     percent_str = (gchar *)strtok(NULL, ":");
580 
581     /* Now, update widgets */
582     if (title)
583       gtk_entry_set_text(GTK_ENTRY(titleWidget),     title);
584     if ((next_title) && (strlen(next_title)))
585       gtk_entry_set_text(GTK_ENTRY(nextTitleWidget), next_title);
586 
587     if ((left == NULL) || (*left == 0))
588       gtk_progress_bar_pulse(GTK_PROGRESS_BAR(progress));
589     else
590     {
591       if ((percent_str) && (strlen(percent_str)))
592       {
593         int percentage, hour, min, sec, left_sec;
594         gchar statusText[100];
595         memset(statusText, 0, 100);
596 
597         left_sec = atoi(left);
598         hour = left_sec / 3600;
599         min  = (left_sec / 60) - (hour*60);
600         sec  = left_sec - (hour*3600) - (min*60);
601         percentage = atoi(percent_str);
602         gtk_progress_set_percentage(GTK_PROGRESS(progress), ((float)percentage / 100.0));
603         snprintf(statusText, 100, "%dh %dm %ds (%d%%)", hour, min, sec, percentage);
604         gtk_progress_bar_set_text(GTK_PROGRESS_BAR(progress), statusText);
605       }
606     }
607 
608     g_free(line);
609 
610   } else if (condition & G_IO_HUP) {
611     if (g_object_get_data(G_OBJECT(mainWindow), "stopping") != NULL)
612       g_object_set_data(G_OBJECT(mainWindow), "stopping", NULL);
613     else
614       ErrorBox(mainWindow, gettext("cPige exited.\n"));
615 
616     startButton = GTK_WIDGET(lookup_widget(GTK_WIDGET(mainWindow), "startButton"));
617     gtk_button_set_label(GTK_BUTTON(startButton), gettext("Start"));
618     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(startButton), FALSE);
619 
620     return FALSE;
621   } else {
622     g_printf("Uncatched event received: %d\n", condition);
623     return FALSE;
624   }
625 }
626