2
gkrellkam2 -- image watcher plugin for GKrellM
3
Copyright (C) 2001-2002 paul cannon
5
This program is free software; you can redistribute it and/or
6
modify it under the terms of the GNU General Public License
7
as published by the Free Software Foundation; either version 2
8
of the License, or (at your option) any later version.
10
This program is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
GNU General Public License for more details.
15
You should have received a copy of the GNU General Public License
16
along with this program; if not, write to the Free Software
17
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20
To contact the author try:
21
paul cannon <pik@debian.org>
25
I use (gchar *) for a string's type when the array is dynamically
26
allocated with the g_* functions, and will eventually need to be
27
g_free'd. Strings of type (char *) are static memory.
31
# include <gkrellm2/gkrellm.h>
35
# include <src/gkrellm.h>
36
# include <src/win32-plugin.h>
43
#define PLUGIN_VER "2.0.0"
45
#define PLUGIN_NAME "GKrellKam"
46
#define PLUGIN_DESC "GKrellM Image Watcher plugin"
47
#define PLUGIN_URL "http://gkrellkam.sf.net/"
48
#define PLUGIN_STYLE PLUGIN_NAME
49
#define PLUGIN_KEYWORD PLUGIN_NAME
51
#define TEMPTEMPLATE "/tmp/krellkam"
55
static gchar *kkam_info_text[] =
57
"<b>" PLUGIN_NAME " " PLUGIN_VER "\n\n",
59
"GKrellKam is a plugin that can watch a number of image files,\n",
60
"and display them sized to fit in panels on your gkrellm.\n\n",
62
"You can ", "<b>left-click", " on an image panel to display the\n",
63
"original, unsized image, or you can ", "<b>middle-click", " on it\n",
64
"to get an immediate update.\n\n",
66
"Scrolling the mouse wheel up over any of the panels increases\n",
67
"the number of visible panels, and scrolling it down decreases\n",
68
"the number. This is so you can hide panels you don't always want\n",
71
"You can also ", "<b>right-click", " on a panel to open the\n",
72
"configuration window.",
75
"<b>-- EASY START --\n\n",
77
"Just put the address of a webcam image in the Image Source\n",
78
"box on the configuration tab for one of the panels. The\n",
79
"address will probably start with \"http://\" and end in \".jpg\",\n",
80
"\".png\", or \".gif\".\n\n",
82
"<b>-- CONFIGURATION TABS --\n\n",
84
"<b>Global Options\n\n",
86
"<i>Path to image viewer program\n",
87
"When you left-click on a GKrellKam panel, it will start your\n",
88
"favorite image viewer and display the original, unsized image.\n",
89
"Put the name of the image viewer program in this box. To use\n",
90
"the included GKrellKam internal viewer, just leave this field\n",
91
"blank. Try clicking on the internal viewer window to get the\n",
95
"When something goes wrong with an image download or the parsing\n",
96
"of a list, GKrellKam lets you know. When Popup errors is checked,\n",
97
"the message will appear as a popup window with an \"OK\" button.\n",
98
"When you turn this option off, error messages will be reported\n",
99
"in the tooltip for the image in question. They are not very\n",
100
"visible this way, but perhaps they are less annoying too.\n\n",
102
"<i>Number of panels\n",
103
"This lets you adjust the number of visible GKrellKam panels\n",
104
"between 0 and 5.\n\n",
106
"<b>Panel Config Tabs\n\n",
108
"<i>Default number of seconds per update\n",
109
"After an image has been successfully loaded, GKrellKam will\n",
110
"wait this many seconds before updating the image. Updating\n",
111
"might involve reloading the same image, or getting the next\n",
112
"image in a list. If you middle-click on a panel, it will do\n",
113
"the update immediately. This setting can be overridden by\n",
114
"specific items in lists.\n\n",
116
"<i>Height of viewer, in pixels\n",
117
"You can adjust this for each panel to give your pictures a\n",
118
"nice-looking aspect.\n\n",
121
"Adds a border space around the image to match better with\n",
122
"your GKrellM theme.\n\n",
124
"<i>Maintain aspect ratio\n",
125
"When checked, images are not sized to fit perfectly in this\n",
126
"panel. They maintain their aspect, and theme background is\n",
127
"shown on either the sides or the top and bottom.\n\n",
129
"<i>Select list images at random\n",
130
"When this is checked, and your image source is a list, then\n",
131
"images will be taken from the list at random rather than\n",
132
"cycled through one by one.\n\n",
135
"Each panel has a \"source\" associated with it. A source can be\n",
136
"a local picture, the web address of a picture, a list of\n",
137
"pictures, or a script to call to get a new picture. To give a\n",
138
"local picture file, list of files, or a script, enter the\n",
139
"_full_ filename in the \"Image Source\" box. To watch a webcam\n",
140
"or other online picture, or use an online list, just put its\n",
141
"address (beginning with http:// or ftp://) in the \"Image Source\n",
142
"box. Lists should end in \"-list\" or \".list\". You'll need GNU\n",
143
"wget installed to be able to get files from the internet.\n",
144
"Special case: when this field begins with \"-x\" followed by a\n",
145
"space and some more text, the remaining text is assumed to be a\n",
146
"script or other system commmand, and the whole path does not\n",
147
"need to be specified.\n\n",
149
"<i>Reread source button\n",
150
"When your image source is a list, GKrellKam will only read in\n",
151
"that list once. If it is changed, and you want GKrellKam to\n",
152
"follow the changes, you can hit the \"Reread source\" button.\n",
153
"This will restart the list. If the source is a script, it will\n",
154
"be re-executed. Other sources will be reread as well.\n\n",
156
"See the included example list, the ",
157
"<b>gkrellkam-list(5)",
160
" online for more info."
163
static gchar *kkam_about_text = _(
164
PLUGIN_NAME " " PLUGIN_VER
166
"\n\nCopyright (C) 2001 paul cannon\n"
167
"paul@cannon.cs.usu.edu\n"
168
"space software lab/utah state university\n\n"
169
PLUGIN_NAME " comes with ABSOLUTELY NO WARRANTY;\n"
170
"see the file COPYING for details.\n\n"
173
static const char *default_source[] = {
174
"http://aggies.usu.edu/webcam/fullsize.jpg",
181
#define wget_opts "--cache=off"
183
#define MIN_NUMPANELS 0
184
#define MAX_NUMPANELS 5
186
#define MAX_SECONDS 604800 /* one week */
196
/* source information structure- panels each have a GList of these */
209
/* items that each panel needs */
221
gboolean maintain_aspect;
225
GtkWidget *period_spinner;
226
GtkWidget *boundary_spinner;
227
GtkWidget *height_spinner;
228
GtkWidget *aspect_box;
229
GtkWidget *random_box;
230
GtkWidget *sourcebox;
249
static GkrellmMonitor *monitor;
251
static GkrellmTicks *pGK;
253
static int created = 0;
254
static int numpanels = 0;
255
static int newnumpanels = 1;
256
static KKamPanel *panels = NULL;
258
static GkrellmStyle *img_style = NULL;
259
static gint style_id;
261
static char *viewer_prog = NULL;
262
static int popup_errors = 0;
264
static GtkWidget *viewerbox;
265
static GtkWidget *numpanel_spinner = NULL;
266
static GtkWidget *popup_errors_box = NULL;
267
static GtkWidget *tabs = NULL;
268
static GtkWidget *kkam_vbox = NULL;
269
static GtkWidget *filebox = NULL;
271
static GtkTooltips *tooltipobj;
273
static void change_num_panels ();
274
static void create_sources_list (KKamPanel *p);
275
static void kkam_read_list (KKamPanel *p, char *listname, int depth);
277
static KKamSource empty_source = { "", "No config",
281
static char *IMG_EXTENSIONS[] = {
297
if popup errors are on, brings up a message window.
298
if not, sets the tooltip text to a warning.
300
static void report_error (KKamPanel *p, char *fmt, ...)
306
str = g_strdup_vprintf (fmt, ap);
311
GtkWidget *label, *vbox, *dialog;
313
dialog = gtk_dialog_new_with_buttons(_("GKrellKam warning:"),
314
NULL, GTK_DIALOG_DESTROY_WITH_PARENT,
315
GTK_STOCK_OK, GTK_RESPONSE_NONE,
317
g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
318
G_CALLBACK(gtk_widget_destroy), GTK_OBJECT(dialog));
320
vbox = gtk_vbox_new (FALSE, 0);
321
gtk_container_set_border_width(GTK_CONTAINER(vbox), 8);
322
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), vbox,
325
label = gtk_label_new (_("GKrellKam warning:"));
326
gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
327
label = gtk_label_new (str);
328
gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
330
gtk_widget_show_all (dialog);
334
if (p && tooltipobj && p->panel && p->panel->drawing_area)
335
gtk_tooltips_set_tip (tooltipobj, p->panel->drawing_area, str, NULL);
340
kkam_add_menu_item ()
342
Used to add a simple item to a menu more easily
344
static void kkam_add_menu_item (GtkWidget *menu, char *label,
345
GtkSignalFunc cb, gpointer d)
349
mi = gtk_menu_item_new_with_label (label);
350
g_signal_connect_swapped (G_OBJECT (mi), "activate", G_CALLBACK(cb), d);
351
gtk_widget_show (mi);
352
gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
358
The delete_event callback for the internal viewer
360
static void kkam_iv_destroy (ViewerInfo *vi)
363
gtk_widget_destroy (vi->fdialog);
364
g_object_unref (G_OBJECT(vi->pixbuf));
365
gtk_widget_destroy (vi->menu);
366
gtk_widget_destroy (vi->window);
373
Turns off the viewer's "Save as" file dialog and sets the pointer
376
static void kkam_iv_donesave (ViewerInfo *vi)
378
gtk_widget_destroy (vi->fdialog);
385
Called when user hits ok on the "Save as" file dialog. Gets the
386
filename, closes the file dialog, and saves the image appropriately.
387
gdk_pixbuf_save() supports only "png" or "jpeg" in Gtk+-2.0.
389
static void kkam_iv_dosave (ViewerInfo *vi)
392
char *type = NULL, *s;
395
gtk_file_selection_get_filename (GTK_FILE_SELECTION (vi->fdialog)));
396
kkam_iv_donesave (vi);
397
if ((s = strstr(fname, ".png")) != NULL)
399
else if ((s = strstr(fname, ".jpg")) != NULL)
401
else if ((s = strstr(fname, ".jpeg")) != NULL)
405
report_error(NULL, "Saved images must be .jpg or .png only.\n", NULL);
409
gdk_pixbuf_save(vi->pixbuf, fname, type, NULL, NULL);
416
Opens the "Save as" file dialog for an image displayed on the
419
static void kkam_iv_saveas (ViewerInfo *vi)
423
gdk_window_raise (vi->fdialog->window);
427
vi->fdialog = gtk_file_selection_new (_("Save As:"));
429
g_signal_connect_swapped (
430
G_OBJECT (GTK_FILE_SELECTION (vi->fdialog)->ok_button),
432
G_CALLBACK (kkam_iv_dosave), (gpointer)vi);
433
g_signal_connect_swapped (
434
G_OBJECT (GTK_FILE_SELECTION (vi->fdialog)->cancel_button),
436
G_CALLBACK (kkam_iv_donesave), (gpointer)vi);
437
gtk_widget_show (vi->fdialog);
443
Creates the popup menu seen when left- or right- clicking on the
446
static void kkam_iv_makemenu (ViewerInfo *vi)
448
vi->menu = gtk_menu_new ();
449
kkam_add_menu_item (vi->menu, _("Close"),
450
GTK_SIGNAL_FUNC (kkam_iv_destroy), (gpointer)vi);
451
kkam_add_menu_item (vi->menu, _("Save As.."),
452
GTK_SIGNAL_FUNC (kkam_iv_saveas), (gpointer)vi);
458
Shows the popup menu after user left- or right- clicks on the
461
static gint kkam_iv_popup (ViewerInfo *vi, GdkEventButton *ev)
463
if (ev->button == 1 || ev->button == 3)
464
gtk_menu_popup (GTK_MENU (vi->menu), NULL, NULL, NULL, NULL,
465
ev->button, ev->time);
472
Rerenders the image when a user resizes the internal viewer window
474
static gint kkam_iv_resize (ViewerInfo *vi, GdkEventConfigure *ev)
476
GdkPixmap *pix = NULL;
477
GdkBitmap *bit = NULL;
479
gkrellm_scale_pixbuf_to_pixmap(vi->pixbuf, &pix, &bit,
480
ev->width, ev->height);
482
gtk_image_set_from_pixmap (GTK_IMAGE (vi->pmap), pix, bit);
483
g_object_unref(G_OBJECT(pix));
485
g_object_unref(G_OBJECT(bit));
491
kkam_internal_viewer ()
493
Opens a very simple full-size image viewer window for the image in
494
question. Users can specify an external viewer if they don't like it :)
496
static void kkam_internal_viewer (char *filename)
499
GdkPixmap *pix = NULL;
500
GdkBitmap *bit = NULL;
503
vi = g_new0 (ViewerInfo, 1);
504
if ((vi->pixbuf = gdk_pixbuf_new_from_file (filename, NULL)) == NULL)
511
kkam_iv_makemenu (vi);
512
vi->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
513
gtk_window_set_title (GTK_WINDOW (vi->window), filename);
514
g_signal_connect_swapped (G_OBJECT (vi->window), "delete_event",
515
G_CALLBACK (kkam_iv_destroy),
517
g_signal_connect_swapped (G_OBJECT (vi->window), "configure_event",
518
G_CALLBACK (kkam_iv_resize),
520
// gtk_window_set_policy (GTK_WINDOW (vi->window), TRUE, TRUE, FALSE);
521
gtk_window_set_wmclass (GTK_WINDOW (vi->window), "KKamViewer", "GKrellm");
523
gkrellm_scale_pixbuf_to_pixmap(vi->pixbuf, &pix, &bit,
524
gdk_pixbuf_get_width(vi->pixbuf),
525
gdk_pixbuf_get_height(vi->pixbuf));
527
vi->pmap = gtk_image_new_from_pixmap(pix, bit);
528
g_object_unref(G_OBJECT(pix));
530
g_object_unref(G_OBJECT(bit));
532
ebox = gtk_event_box_new ();
533
gtk_container_add (GTK_CONTAINER (ebox), vi->pmap);
534
gtk_container_add (GTK_CONTAINER (vi->window), ebox);
535
gtk_widget_set_events (ebox, GDK_BUTTON_PRESS_MASK);
536
g_signal_connect_swapped (G_OBJECT (ebox), "button_press_event",
537
G_CALLBACK (kkam_iv_popup), (gpointer)vi);
538
gtk_widget_show_all (vi->window);
544
returns TRUE if the given number is a valid index
545
into the panels array
547
static gboolean validnum (int num)
549
return (panels && num >= 0 && num < MAX_NUMPANELS);
555
returns TRUE if the given number is an active index
556
into the panels array
558
static gboolean activenum (int num)
560
return (panels && num >= 0 && num < numpanels);
566
returns a pointer to the source definition of the current image for
567
the current panel, or &empty_source if none.
569
static KKamSource *panel_cursource (KKamPanel *p)
571
if (p->sources == NULL)
572
return &empty_source;
573
return (KKamSource *)(p->sources->data);
579
returns the time that should elapse before the current image is
580
changed. If the current source's seconds member is 0, use the
583
static int get_period (KKamPanel *p)
587
if ((per = panel_cursource (p)->seconds) == 0)
588
return p->default_period;
595
If a kkamsource has been loaded before, and a copy of the image
596
is still attached to it, then unattach that copy. If it is a
597
temporary file, then unlink it as well.
599
static void tfile_release (KKamSource *ks)
601
if (ks == NULL || ks->tfile == NULL)
604
if (ks->type == SOURCE_URL)
614
renders the current image into the panel at the right size.
615
aspect-scaling patch from Benjamin Johnson (benj@visi.com)- thanks
617
static void draw_pixbuf (KKamPanel *p)
619
int pan_x, pan_y; /* panel x and y sizes */
620
int scale_x, scale_y; /* size of scaled image */
621
int loc_x, loc_y; /* location for scaled image */
622
int image_w, image_h;
624
if (p->pixbuf == NULL)
627
pan_x = gkrellm_chart_width () - 2 * p->boundary;
628
pan_y = p->height - 2 * p->boundary;
630
image_w = gdk_pixbuf_get_width(p->pixbuf);
631
image_h = gdk_pixbuf_get_height(p->pixbuf);
633
if (p->maintain_aspect)
635
/* determine sizing here - maintain aspect ratio */
637
if (pan_x >= image_w && pan_y >= image_h)
639
/* the image is smaller then the panel. do no sizing, just center. */
641
loc_x = (pan_x - image_w) / 2 + p->boundary;
642
loc_y = (pan_y - image_h) / 2 + p->boundary;
644
scale_x = 0; /* scale of 0 defaults to use image size */
647
else if ((double) image_w / (double)pan_x >
648
(double) image_h / (double)pan_y)
650
/* scale to width (image is wider compared to panel size) */
653
scale_y = image_h * pan_x / image_w;
656
loc_y = (pan_y - scale_y) / 2 + p->boundary;
660
/* scale to height (image is taller compared to panel size) */
662
scale_x = image_w * pan_y / image_h;
665
loc_x = (pan_x - scale_x) / 2 + p->boundary;
671
/* Scale to size of panel */
680
gkrellm_destroy_decal (p->decal);
681
gkrellm_scale_pixbuf_to_pixmap (p->pixbuf, &(p->pixmap), NULL,
684
p->decal = gkrellm_create_decal_pixmap (p->panel, p->pixmap,
685
NULL, 1, img_style, loc_x, loc_y);
686
gkrellm_draw_decal_pixmap (p->panel, p->decal, 0);
687
gkrellm_draw_panel_layers (p->panel);
693
Open a pipe and spawn wget.
695
static void start_img_dl (KKamPanel *p)
698
char tmpfile[] = TEMPTEMPLATE "XXXXXX";
701
if (p->cmd_pipe) /* already open */
704
tmpfd = mkstemp (tmpfile); /* this will create the file, perm 0600 */
707
report_error (p, _("Couldn't create temporary file for download: %s"),
713
wget_str = g_strdup_printf ("wget -q %s -O %s \"%s\"",
715
panel_cursource (p)->img_name);
717
p->cmd_pipe = popen (wget_str, "r");
719
if (p->cmd_pipe == NULL)
722
report_error (p, _("Couldn't start wget: %s"), strerror (errno));
726
panel_cursource (p)->tfile = g_strdup (tmpfile);
727
fcntl (fileno (p->cmd_pipe), F_SETFL, O_NONBLOCK);
733
open a pipe for a user-defined script
735
static void start_script_dl (KKamPanel *p)
739
if (p->cmd_pipe) /* already open */
742
scriptname = panel_cursource (p)->img_name;
743
if (!strncmp (scriptname, "-x", 2))
746
p->cmd_pipe = popen (scriptname, "r");
747
if (p->cmd_pipe == NULL)
749
report_error (p, _("Couldn't start script \"%s\": %s\n"),
750
panel_cursource (p)->img_name, strerror (errno));
753
fcntl (fileno (p->cmd_pipe), F_SETFL, O_NONBLOCK);
759
If the file in p's cursource exists, loads it into p's pixbuf
760
member. Calls draw_pixbuf. Also, sets image tooltip.
762
Returns -1 on file missing, and 1 otherwise (not necessarily
763
success, but probably)
765
static int load_image_file (KKamPanel *p)
770
ks = panel_cursource (p);
772
/* make sure file is really there. when the imlib stuff
773
fails it's really loud */
774
if (ks->tfile == NULL || stat (ks->tfile, &img_st) == -1)
781
g_object_unref (G_OBJECT(p->pixbuf));
782
p->pixbuf = gdk_pixbuf_new_from_file (ks->tfile, NULL);
786
gtk_tooltips_set_tip (tooltipobj, p->panel->drawing_area,
789
gtk_tooltips_set_tip (tooltipobj, p->panel->drawing_area,
798
Checks if the command pipe is dead yet. If so, checks its output
799
status and returns 1 if the command was successful.
801
On error, returns -1. On not yet ready, returns 0.
803
static int cmd_results (KKamPanel *p)
809
ks = panel_cursource (p);
811
if (fread (buf, sizeof (char), 1, p->cmd_pipe) < 1)
813
/* if we get EAGAIN, wait some more */
814
if (ferror (p->cmd_pipe) && errno == EAGAIN)
817
/* if we reach here the pipe is dead- the command has finished. */
818
code = pclose (p->cmd_pipe);
821
/* pclose will return a -1 on a wait4 error. If that happens,
822
we have no way to know whether wget succeeded. Just try */
823
if (ks->type == SOURCE_URL && code <= 0)
825
ks->next_dl = time (NULL) + ks->tlife;
830
report_error (p, _("Error: wget gave bad code or script died. code %d"),
835
len = fread (&buf[1], sizeof (char), BUFLEN - 2, p->cmd_pipe);
839
pclose (p->cmd_pipe);
842
if (ks->type == SOURCE_SCRIPT)
844
ks->tfile = g_strdup (buf);
845
ks->next_dl = time (NULL) + ks->tlife;
851
/* if we get here with wget, then wget said something. This is generally
852
not good, since we passed -q. We'll have to wait for it to die */
854
report_error (p, _("wget said: \"%s\""), buf);
862
moves the current source item to the end of the list, unless
865
static void rotate_sources (KKamPanel *p)
870
if (p == NULL || p->sources == NULL ||
871
(len = g_list_length (p->sources)) == 1)
874
times = p->random ? (rand () % (len - 1) + 1) : 1;
875
for (i = 0; i < times; i++)
878
p->sources = g_list_remove_link (p->sources, link);
879
p->sources = g_list_concat (p->sources, link);
886
determines what the current image source is, and updates or
887
starts an update as appropriate
889
static void update_image (KKamPanel *p)
893
p->count = get_period (p);
895
ks = panel_cursource (p);
896
if (ks->img_name == NULL || ks->img_name[0] == '\0')
899
if (ks->next_dl > time (NULL))
914
ks->tfile = g_strdup (ks->img_name);
915
ks->next_dl = 0; /* next_dl is meaningless for SOURCE_FILE */
919
report_error (p, _("Invalid type %d found in sources list!"), ks->type);
927
when the listurl download is finished, reads the list and deletes it.
928
Returns 0 if still waiting, 1 on success or error.
930
static int listurl_results (KKamPanel *p)
936
ks = panel_cursource (p);
938
if (fread (&c, sizeof (char), 1, p->listurl_pipe) < 1)
940
/* if we get EAGAIN, wait some more */
941
if (ferror (p->listurl_pipe) && errno == EAGAIN)
944
/* if we reach here the pipe is dead- the command has finished. */
945
code = pclose (p->listurl_pipe);
946
p->listurl_pipe = NULL;
951
/* pclose will return a -1 on a wait4 error. If that happens,
952
we have no way to know whether wget succeeded. Just try */
955
kkam_read_list (p, p->listurl_file, 0);
959
report_error (p, _("Error: wget listurl download died. code %d"), code);
961
unlink (p->listurl_file);
962
g_free (p->listurl_file);
963
p->listurl_file = NULL;
969
kkam_update_plugin ()
971
callback from gkrellm. Counts seconds until next update, and when
972
count is reached, starts the update process.
974
static void kkam_update_plugin ()
978
if (pGK->second_tick)
979
for (i = 0; i < numpanels; i++)
981
if (panels[i].listurl_pipe)
982
listurl_results (&panels[i]);
983
else if (panels[i].cmd_pipe)
984
cmd_results (&panels[i]);
985
else if (--panels[i].count <= 0)
987
rotate_sources (&panels[i]);
988
update_image (&panels[i]);
993
void showsource (KKamSource *s)
995
fprintf (stderr, "name %s, type %d, seconds %d, tooltip %s\n",
996
s->img_name, s->type, s->seconds, s->tooltip);
1000
wheel_callback(GtkWidget *widget, GdkEventScroll *ev)
1002
if (ev->direction == GDK_SCROLL_UP)
1004
newnumpanels = MIN (numpanels + 1, MAX_NUMPANELS);
1005
change_num_panels ();
1007
else if (ev->direction == GDK_SCROLL_DOWN)
1009
newnumpanels = MAX (numpanels - 1, MIN_NUMPANELS);
1010
change_num_panels ();
1018
Process user's mouse-clicks on the panels. Open viewers, refresh images,
1019
increase/decrease number of panels, etc.
1021
static gint click_callback (GtkWidget *widget, GdkEventButton *ev, gpointer gw)
1027
which = GPOINTER_TO_INT (gw);
1028
if (!activenum (which))
1031
ks = panel_cursource (&panels[which]);
1035
case 1: /* view image */
1038
if (viewer_prog == NULL || viewer_prog[0] == '\0')
1039
kkam_internal_viewer (ks->tfile);
1042
cmd = g_strdup_printf ("%s '%s' &", viewer_prog, ks->tfile);
1048
case 2: /* immediate update */
1049
panels[which].count = 0;
1054
gkrellm_open_config_window (monitor);
1061
static gint panel_expose_event (GtkWidget *widget,
1067
which = GPOINTER_TO_INT (gw);
1068
if (!activenum (which))
1071
gdk_draw_drawable (widget->window,
1072
widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
1073
panels[which].panel->pixmap,
1074
ev->area.x, ev->area.y, ev->area.x, ev->area.y,
1075
ev->area.width, ev->area.height);
1080
static void cb_aspect_box (KKamPanel *p)
1082
p->maintain_aspect = GTK_TOGGLE_BUTTON (p->aspect_box)->active;
1083
gkrellm_config_modified ();
1087
static void cb_boundary_spinner (gpointer w, KKamPanel *p)
1089
p->boundary = gtk_spin_button_get_value_as_int
1090
(GTK_SPIN_BUTTON (p->boundary_spinner));
1091
gkrellm_config_modified ();
1095
static void cb_height_spinner (gpointer w, KKamPanel *p)
1099
newheight = gtk_spin_button_get_value_as_int (
1100
GTK_SPIN_BUTTON (p->height_spinner));
1102
if (newheight != p->height)
1104
gkrellm_panel_configure_add_height (p->panel, newheight - p->height);
1105
p->height = newheight;
1106
gkrellm_panel_create (kkam_vbox, monitor, p->panel);
1108
gkrellm_config_modified ();
1116
sets the image source from the file selection dialog
1118
static void src_set (KKamPanel *p)
1121
p->source = g_strdup (gtk_file_selection_get_filename (
1122
GTK_FILE_SELECTION (filebox)));
1123
gkrellm_config_modified ();
1124
gtk_entry_set_text (GTK_ENTRY (p->sourcebox), p->source);
1125
gtk_widget_destroy (GTK_WIDGET (filebox));
1126
create_sources_list (p);
1127
p->count = get_period (p);
1134
brings up a file browser window to select a source
1136
static void srcbrowse (KKamPanel *p)
1138
filebox = gtk_file_selection_new (_("Select Image Source"));
1139
g_signal_connect_swapped (
1140
G_OBJECT (GTK_FILE_SELECTION (filebox)->ok_button),
1141
"clicked", G_CALLBACK (src_set), (gpointer)p);
1142
g_signal_connect_swapped (
1143
G_OBJECT (GTK_FILE_SELECTION (filebox)->cancel_button),
1145
G_CALLBACK (gtk_widget_destroy),
1148
gtk_widget_show (filebox);
1154
rereads the source of a panel- this is useful if, for example,
1155
one changes a list and wants the new list used
1157
static void srcreread (KKamPanel *p)
1160
p->source = gtk_editable_get_chars (GTK_EDITABLE (p->sourcebox), 0, -1);
1161
create_sources_list (p);
1162
p->count = get_period (p);
1167
create_configpanel_tab ()
1169
Creates a GtkVbox for the configuration of one of the panels
1171
static GtkWidget *create_configpanel_tab (int i)
1173
GtkWidget *vbox, *hbox, *button, *sourcelabel;
1175
vbox = gtk_vbox_new (FALSE, 0);
1177
gkrellm_gtk_spin_button (vbox, &panels[i].period_spinner,
1178
(gfloat) panels[i].default_period,
1179
1.0, (gfloat)MAX_SECONDS, 1.0, 10.0, 0, 0, NULL, NULL,
1180
FALSE, _("Default number of seconds per update"));
1182
gkrellm_gtk_spin_button (vbox, &panels[i].height_spinner,
1183
(gfloat) panels[i].height,
1184
10.0, 100.0, 1.0, 5.0, 0, 0, cb_height_spinner, &panels[i],
1185
FALSE, _("Height of viewer, in pixels"));
1187
hbox = gtk_hbox_new (FALSE, 0);
1188
gkrellm_gtk_spin_button (hbox, &panels[i].boundary_spinner,
1189
(gfloat) panels[i].boundary,
1190
0.0, 20.0, 1.0, 1.0, 0, 0, cb_boundary_spinner, &panels[i],
1191
FALSE, _("Border size"));
1193
gkrellm_gtk_check_button (hbox, &panels[i].aspect_box,
1194
panels[i].maintain_aspect,
1195
TRUE, 0, _("Maintain aspect ratio"));
1196
gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
1198
g_signal_connect_swapped (G_OBJECT (panels[i].aspect_box), "toggled",
1199
G_CALLBACK (cb_aspect_box), (gpointer)&panels[i]);
1201
gkrellm_gtk_check_button (vbox, &panels[i].random_box,
1203
TRUE, 0, _("Select list images at random"));
1205
hbox = gtk_hbox_new (FALSE, 0);
1206
sourcelabel = gtk_label_new (_("Image source: "));
1207
panels[i].sourcebox = gtk_entry_new ();
1208
gtk_entry_set_text (GTK_ENTRY (panels[i].sourcebox), panels[i].source);
1209
button = gtk_button_new_with_label (_("Browse.."));
1210
g_signal_connect_swapped (G_OBJECT (button), "clicked",
1211
G_CALLBACK (srcbrowse), (gpointer)&panels[i]);
1212
gtk_box_pack_start (GTK_BOX (hbox), sourcelabel, FALSE, FALSE, 0);
1213
gtk_box_pack_start (GTK_BOX (hbox), panels[i].sourcebox, TRUE, TRUE, 0);
1214
gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
1215
gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, FALSE, 0);
1217
hbox = gtk_hbox_new (FALSE, 5);
1218
button = gtk_button_new_with_label (_("Reread source"));
1219
g_signal_connect_swapped (G_OBJECT (button), "clicked",
1220
G_CALLBACK (srcreread), (gpointer)&panels[i]);
1221
gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
1222
gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, FALSE, 0);
1224
gtk_widget_show_all (vbox);
1230
insert_configpanel_tab ()
1232
Creates a new configuration tab and inserts it into the config box
1234
static void insert_configpanel_tab (int i)
1236
GtkWidget *label, *configpanel;
1239
if (!GTK_IS_OBJECT (tabs))
1242
configpanel = create_configpanel_tab (i);
1244
labeltxt = g_strdup_printf (_("Panel #%i"), i + 1);
1245
label = gtk_label_new (labeltxt);
1248
gtk_notebook_insert_page (GTK_NOTEBOOK (tabs), configpanel, label, i + 1);
1252
remove_configpanel_tab ()
1254
Removes a configuration tab from the config box
1256
static void remove_configpanel_tab (int i)
1258
if (!GTK_IS_OBJECT (tabs))
1261
gtk_notebook_remove_page (GTK_NOTEBOOK (tabs), i + 1);
1265
change_num_panels ()
1267
called to move the number in `newnumpanels' into
1268
`numpanels' with all associated changes to the monitor
1270
static void change_num_panels ()
1274
if (numpanels == newnumpanels)
1279
for (i = numpanels - 1; i >= newnumpanels; i--)
1281
remove_configpanel_tab (i);
1282
if (panels[i].cmd_pipe)
1284
pclose (panels[i].cmd_pipe);
1285
panels[i].cmd_pipe = NULL;
1289
for (i = 0; i < MAX_NUMPANELS; i++)
1291
gkrellm_panel_enable_visibility (panels[i].panel, i < newnumpanels,
1292
&(panels[i].visible));
1295
for (i = numpanels; i < newnumpanels; i++)
1297
insert_configpanel_tab (i);
1298
update_image (&panels[i]);
1302
numpanels = newnumpanels;
1303
gkrellm_config_modified ();
1306
static void kkam_create_plugin (GtkWidget *vbox, gint first_create)
1314
change_num_panels ();
1317
for (i = 0; i < MAX_NUMPANELS; i++)
1318
panels[i].panel = gkrellm_panel_new0 ();
1320
tooltipobj = gtk_tooltips_new ();
1322
srand (time (NULL)); /* randomize from timer */
1325
img_style = gkrellm_meter_style (style_id);
1327
for (i = 0; i < MAX_NUMPANELS; i++)
1329
gkrellm_panel_configure_add_height (panels[i].panel, panels[i].height);
1330
gkrellm_panel_create (vbox, monitor, panels[i].panel);
1331
gkrellm_panel_keep_lists (panels[i].panel, TRUE);
1333
panels[i].visible = TRUE;
1336
gkrellm_panel_enable_visibility (panels[i].panel, FALSE,
1337
&(panels[i].visible));
1343
for (i = 0; i < MAX_NUMPANELS; i++)
1345
g_signal_connect (G_OBJECT (panels[i].panel->drawing_area),
1346
"expose_event", G_CALLBACK (panel_expose_event),
1347
GINT_TO_POINTER (i));
1348
g_signal_connect (G_OBJECT (panels[i].panel->drawing_area),
1349
"button_press_event", G_CALLBACK (click_callback),
1350
GINT_TO_POINTER (i));
1351
g_signal_connect (G_OBJECT (panels[i].panel->drawing_area),
1352
"scroll_event", G_CALLBACK (wheel_callback), NULL);
1354
gkrellm_draw_panel_layers (panels[i].panel);
1356
update_image (&panels[i]);
1361
for (i = 0; i < numpanels; i++)
1362
if (panels[i].decal && panels[i].decal->pixmap)
1364
gkrellm_draw_decal_pixmap (panels[i].panel, panels[i].decal, 0);
1365
gkrellm_draw_panel_layers (panels[i].panel);
1370
static KKamSource *kkam_source_new ()
1372
return g_new0 (KKamSource, 1);
1375
static void kkam_source_free (KKamSource *ks)
1379
g_free (ks->img_name);
1380
g_free (ks->tooltip);
1384
static void destroy_sources_list (KKamPanel *p)
1386
g_list_foreach (p->sources, (GFunc)kkam_source_free, NULL);
1387
g_list_free (p->sources);
1392
addto_sources_list ()
1394
Adds a component to the sources list for panel p. The name
1395
and type are copied from name and type. The new component
1396
is returned, in case it needs to be modified further.
1398
static KKamSource *addto_sources_list (KKamPanel *p, char *name, SourceEnum type)
1402
ks = kkam_source_new ();
1404
ks->img_name = g_strdup (name);
1407
p->sources = g_list_append (p->sources, (gpointer)ks);
1415
returns TRUE if the end of str matches endstr
1417
static gboolean endswith (char *str, char *endstr)
1421
if ((len = strlen (str)) < (lenend = strlen (endstr)))
1423
return !strcmp (&str[len - lenend], endstr);
1429
determines what type of source is represented by the given
1430
string, according to these rules, checked in order:
1432
- A source beginning with 'http:' or 'ftp:' and ending in '.list'
1433
is a SOURCE_LISTURL.
1434
- A source beginning with 'http:' or 'ftp:' is a SOURCE_URL.
1435
- A source that begins with '-x' is a SOURCE_SCRIPT.
1436
- A source with an extension in IMG_EXTENSIONS is a SOURCE_FILE.
1437
- A source that matches a filename that is executable by the user is
1439
- A source ending in [.-]list is a SOURCE_LIST.
1440
- If none of the above apply, and the source is a filename, the
1441
file is opened. If it 'looks' like a GKrellKam list configuration
1442
file, it is a SOURCE_LIST.
1443
- Otherwise, it is a SOURCE_FILE.
1447
static SourceEnum source_type_of (char *def)
1452
unsigned char buf[BUFLEN];
1454
words = g_strsplit (def, " ", 2);
1455
if (!words || !words[0]) /* wish I didn't need this */
1458
if (!strncmp (words[0], "http:", 5) || !strncmp (words[0], "ftp:", 4))
1460
if (endswith (words[0], ".list") || endswith (words[0], "-list"))
1463
return SOURCE_LISTURL;
1469
if (!strcmp (words[0], "-x"))
1472
return SOURCE_SCRIPT;
1474
for (i = 0; i < (sizeof (IMG_EXTENSIONS) / sizeof (IMG_EXTENSIONS[0])); i++)
1476
if (endswith (words[0], IMG_EXTENSIONS[i]))
1482
if (access (words[0], X_OK) == 0)
1485
return SOURCE_SCRIPT;
1487
if (endswith (words[0], ".list") || endswith (words[0], "-list"))
1493
if ((test = fopen (words[0], "r")) != NULL)
1495
len = fread (buf, sizeof (buf[0]), BUFLEN, test);
1496
for (p = 0; p < len; p++)
1497
if (!isgraph (buf[p]) && !isspace (buf[p]))
1515
convenience function for the list reader; returns a pointer in s
1516
to the beginning of the next parameter (non-space following a colon)
1518
char *nextword (char *s)
1522
for (ret = s; *ret != ':'; ret++) ;
1524
for ( ; isspace (*ret); ret++) ;
1531
reads a GKrellKam list configuration file and loads its
1532
data into the panel's source GList
1534
static void kkam_read_list (KKamPanel *p, char *listname, int depth)
1536
KKamSource *ks = NULL;
1540
int thislist_error = 0;
1542
if (depth > MAX_DEPTH)
1544
report_error (p, _("Maximum recursion depth exceeded reading list %s; "
1545
"perhaps a list is trying to load itself?"), listname);
1549
if ((listfile = fopen (listname, "r")) == NULL)
1552
while (fgets (buf, BUFLEN, listfile))
1566
if (!strncmp (&buf[1], "tooltip:", 8))
1567
ks->tooltip = g_strdup (nextword (&buf[1]));
1568
else if (!strncmp (&buf[1], "seconds:", 8))
1569
ks->seconds = CLAMP (atoi (nextword (&buf[1])), 1, MAX_SECONDS);
1570
else if (!strncmp (&buf[1], "refresh:", 8))
1571
ks->tlife = CLAMP (atoi (nextword (&buf[1])), 1, MAX_SECONDS);
1573
else if (thislist_error == 0) /* only show one error per file */
1576
report_error (p, _("In list %s, property line \"%s\" isn't associated"
1577
" with any source!"), listname, &buf[1]);
1582
if (!strncmp (buf, "image:", 6))
1583
ks = addto_sources_list (p, nextword (buf), SOURCE_FILE);
1584
else if (!strncmp (buf, "script:", 7))
1585
ks = addto_sources_list (p, nextword (buf), SOURCE_SCRIPT);
1586
else if (!strncmp (buf, "url:", 4))
1587
ks = addto_sources_list (p, nextword (buf), SOURCE_URL);
1588
else if (!strncmp (buf, "list:", 5))
1590
kkam_read_list (p, nextword (buf), depth + 1);
1595
typ = source_type_of (buf);
1596
if (typ == SOURCE_LIST)
1598
kkam_read_list (p, buf, depth + 1);
1602
ks = addto_sources_list (p, buf, typ);
1608
static void kkam_read_listurl (KKamPanel *p, char *source)
1611
char tmpfile[] = TEMPTEMPLATE "-urllistXXXXXX";
1614
if (p->listurl_pipe) /* already open */
1617
tmpfd = mkstemp (tmpfile); /* this will create the file, perm 0600 */
1620
report_error (p, _("Couldn't create temporary file for list download: %s"),
1626
wget_str = g_strdup_printf ("wget -q %s -O %s \"%s\"",
1627
wget_opts, tmpfile, source);
1629
p->listurl_pipe = popen (wget_str, "r");
1631
if (p->listurl_pipe == NULL)
1634
report_error (p, _("Couldn't start wget for list download: %s"),
1639
p->listurl_file = g_strdup (tmpfile);
1640
fcntl (fileno (p->listurl_pipe), F_SETFL, O_NONBLOCK);
1642
gtk_tooltips_set_tip (tooltipobj, p->panel->drawing_area,
1643
_("Downloading list.."), NULL);
1647
create_sources_list ()
1649
Takes the 'source' of a panel- which can be a web address,
1650
local image, script, list, etc.. and translates that into
1651
a GList of sources. For most source types, obviously, the
1652
sources GList will only have one entry.
1654
static void create_sources_list (KKamPanel *p)
1659
destroy_sources_list (p);
1661
if (p->source && p->source[0])
1663
switch (s = source_type_of (p->source))
1668
addto_sources_list (p, p->source, s);
1671
kkam_read_list (p, p->source, 0);
1673
case SOURCE_LISTURL:
1674
kkam_read_listurl (p, p->source);
1681
update_source_config ()
1683
Translates a 0.2.2[bcd]-style config into an appropriate source item
1685
static void update_source_config (KKamPanel *p, char *val)
1692
g_strdelimit (val, " \t\n", '\n');
1693
words = g_strsplit (val, "\n", 0);
1695
for (i = 0; words[i]; i++)
1697
if (!strcmp (words[i], "-l") || !strcmp (words[i], "--list"))
1700
words[i] = g_strdup ("");
1702
else if (!strcmp (words[i], "-x") || !strcmp (words[i], "--execute"))
1705
words[i] = g_strdup ("-x");
1706
scr = g_strjoinv (" ", &words[i]);
1707
addto_sources_list (p, scr, SOURCE_SCRIPT);
1712
else if (!strcmp (words[i], "-r") || !strcmp (words[i], "--random"))
1716
t = source_type_of (words[i]);
1718
p->source = g_strdup (words[i]);
1719
if (t == SOURCE_LIST)
1720
kkam_read_list (p, words[i], 0);
1722
addto_sources_list (p, words[i], source_type_of (val));
1729
update_script_config ()
1731
Translates a pre-0.2.2-style config into an appropriate source item
1733
static void update_script_config (KKamPanel *p, char *val)
1736
char *firstword, *rest;
1738
chopmeup = g_strdup_printf ("%s\n \n", g_strstrip (val));
1739
firstword = strtok (chopmeup, " \n");
1742
rest = strtok (NULL, "\n");
1747
/* If the old update_script item was using krellkam_load, parse
1748
its parameters. If it was using a different script, put it with
1749
the appropriate type into the source list */
1751
if (!strcmp (basename (firstword), "krellkam_load"))
1752
update_source_config (p, rest);
1756
p->source = g_strdup_printf ("-x %s", val);
1757
addto_sources_list (p, val, SOURCE_SCRIPT);
1762
static void kkam_save_config (FILE *f)
1766
if (viewer_prog && viewer_prog[0])
1767
fprintf (f, "%s viewer_prog %s\n", PLUGIN_KEYWORD, viewer_prog);
1769
fprintf (f, "%s popup_errors %d\n", PLUGIN_KEYWORD, popup_errors);
1770
fprintf (f, "%s numpanels %d\n", PLUGIN_KEYWORD, numpanels);
1772
for (i = 0; i < MAX_NUMPANELS; i++)
1774
fprintf (f, "%s %d sourcedef %s\n",
1775
PLUGIN_KEYWORD, i + 1, panels[i].source);
1776
fprintf (f, "%s %d options %d.%d.%d.%d.%d\n",
1777
PLUGIN_KEYWORD, i + 1,
1779
panels[i].default_period,
1781
panels[i].maintain_aspect,
1786
static void kkam_load_config (gchar *arg)
1788
gchar *config_item, *value;
1791
config_item = strtok (arg, " \n");
1794
which = atoi (config_item);
1797
config_item = strtok (NULL, " \n");
1802
value = strtok (NULL, "\n");
1806
if (!strcmp (config_item, "options"))
1808
if (validnum (which))
1810
sscanf (value, "%d.%d.%d.%d.%d",
1811
&(panels[which].height),
1812
&(panels[which].default_period),
1813
&(panels[which].boundary),
1814
&(panels[which].maintain_aspect),
1815
&(panels[which].random));
1817
panels[which].height = CLAMP (panels[which].height, 10, 100);
1818
panels[which].default_period =
1819
CLAMP (panels[which].default_period, 1, MAX_SECONDS);
1820
panels[which].boundary = CLAMP (panels[which].boundary, 0, 20);
1821
panels[which].maintain_aspect =
1822
(gboolean)CLAMP (panels[which].maintain_aspect, 0, 1);
1823
panels[which].random = (gboolean)CLAMP (panels[which].random, 0, 1);
1826
else if (!strcmp (config_item, "sourcedef"))
1828
if (validnum (which))
1830
g_free (panels[which].source);
1831
panels[which].source = g_strstrip (g_strdup (value));
1832
create_sources_list (&panels[which]);
1835
else if (!strcmp (config_item, "viewer_prog"))
1837
g_free (viewer_prog);
1838
viewer_prog = g_strdup (value);
1840
else if (!strcmp (config_item, "popup_errors"))
1842
popup_errors = atoi (value);
1844
else if (!strcmp (config_item, "numpanels"))
1846
newnumpanels = CLAMP (atoi (value), MIN_NUMPANELS, MAX_NUMPANELS);
1847
change_num_panels ();
1849
/* backwards compatibility */
1850
else if (!strcmp (config_item, "img_height"))
1852
if (validnum (which))
1853
panels[which].height = CLAMP (atoi (value), 10, 100);
1855
else if (!strcmp (config_item, "period"))
1857
if (validnum (which))
1858
panels[which].default_period = CLAMP (atoi (value), 1, MAX_SECONDS);
1860
else if (!strcmp (config_item, "maintain_aspect"))
1862
if (validnum (which))
1863
panels[which].maintain_aspect = (gboolean)CLAMP (atoi (value), 0, 1);
1865
else if (!strcmp (config_item, "boundary"))
1867
if (validnum (which))
1868
panels[which].boundary = CLAMP (atoi (value), 0, 20);
1870
else if (!strcmp (config_item, "update_period"))
1872
/* this is in minutes */
1873
if (validnum (which))
1874
panels[which].default_period = MAX (atoi (value) * 60, 1);
1876
else if (!strcmp (config_item, "update_script"))
1878
/* update old config item */
1879
if (validnum (which))
1880
update_script_config (&panels[which], value);
1882
else if (!strcmp (config_item, "source"))
1884
/* backwards compat for 0.2.2[bcd] */
1885
if (validnum (which))
1886
update_source_config (&panels[which], value);
1890
static void cb_numpanel_spinner ()
1892
newnumpanels = gtk_spin_button_get_value_as_int
1893
(GTK_SPIN_BUTTON (numpanel_spinner));
1894
change_num_panels ();
1897
static void kkam_create_tab (GtkWidget *tab_vbox)
1899
GtkWidget *vbox, *tablabel;
1901
GtkWidget *hbox, *configpanel, *about;
1902
GtkAdjustment *numadj;
1907
g_object_unref (G_OBJECT (tabs));
1909
tabs = gtk_notebook_new ();
1910
gtk_notebook_set_tab_pos (GTK_NOTEBOOK (tabs), GTK_POS_TOP);
1911
gtk_box_pack_start (GTK_BOX (tab_vbox), tabs, TRUE, TRUE, 0);
1912
g_object_ref (G_OBJECT (tabs));
1914
/* main options tab */
1915
vbox = gkrellm_gtk_framed_notebook_page (tabs, _("Options"));
1917
hbox = gtk_hbox_new (FALSE, 0);
1918
viewerbox = gtk_entry_new ();
1920
gtk_entry_set_text (GTK_ENTRY (viewerbox), viewer_prog);
1922
gtk_box_pack_start (GTK_BOX (hbox),
1923
gtk_label_new (_("Path to image viewer program:")),
1925
gtk_box_pack_start (GTK_BOX (hbox), viewerbox, FALSE, FALSE, 0);
1926
gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, FALSE, 0);
1928
hbox = gtk_hbox_new (FALSE, 0);
1929
popup_errors_box = gtk_check_button_new_with_label (_("Popup errors"));
1930
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (popup_errors_box),
1932
gtk_box_pack_start (GTK_BOX (hbox), popup_errors_box, FALSE, FALSE, 10);
1933
gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, FALSE, 0);
1935
numadj = (GtkAdjustment *) gtk_adjustment_new ((gfloat) numpanels,
1936
(gfloat) MIN_NUMPANELS,
1937
(gfloat) MAX_NUMPANELS,
1939
numpanel_spinner = gtk_spin_button_new (numadj, 1.0, 0);
1940
g_signal_connect (G_OBJECT (numpanel_spinner), "changed",
1941
G_CALLBACK (cb_numpanel_spinner), NULL);
1942
hbox = gtk_hbox_new (FALSE, 0);
1943
gtk_box_pack_start (GTK_BOX (hbox), numpanel_spinner, FALSE, FALSE, 10);
1944
gtk_box_pack_start (GTK_BOX (hbox),
1945
gtk_label_new (_("Number of panels")),
1947
gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, FALSE, 0);
1949
/* individual panel options tabs */
1950
for (i = 0; i < MAX_NUMPANELS; i++)
1952
configpanel = create_configpanel_tab (i);
1954
tabname = g_strdup_printf (_("Panel #%d"), i + 1);
1955
tablabel = gtk_label_new (tabname);
1959
gtk_notebook_append_page (GTK_NOTEBOOK (tabs), configpanel, tablabel);
1963
vbox = gkrellm_gtk_framed_notebook_page (tabs, _("Info"));
1965
text = gkrellm_gtk_scrolled_text_view(vbox, NULL,
1966
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1968
for (i = 0; i < sizeof(kkam_info_text) / sizeof(gchar *); ++i)
1969
gkrellm_gtk_text_view_append(text, _(kkam_info_text[i]));
1972
vbox = gkrellm_gtk_framed_notebook_page (tabs, _("About"));
1973
about = gtk_label_new (kkam_about_text);
1974
gtk_box_pack_start (GTK_BOX (vbox), about, TRUE, TRUE, 0);
1977
static void kkam_apply_config ()
1982
for (i = 0; i < numpanels; i++)
1984
newsource = gtk_editable_get_chars
1985
(GTK_EDITABLE (panels[i].sourcebox), 0, -1);
1986
diff = strcmp (newsource, panels[i].source);
1987
g_free (panels[i].source);
1988
panels[i].source = newsource;
1990
create_sources_list (&panels[i]);
1992
panels[i].default_period = gtk_spin_button_get_value_as_int
1993
(GTK_SPIN_BUTTON (panels[i].period_spinner));
1994
panels[i].maintain_aspect = GTK_TOGGLE_BUTTON (panels[i].aspect_box)->active;
1995
panels[i].random = GTK_TOGGLE_BUTTON (panels[i].random_box)->active;
1996
panels[i].boundary = gtk_spin_button_get_value_as_int
1997
(GTK_SPIN_BUTTON (panels[i].boundary_spinner));
2000
newnumpanels = gtk_spin_button_get_value_as_int
2001
(GTK_SPIN_BUTTON (numpanel_spinner));
2002
change_num_panels ();
2005
g_free (viewer_prog);
2006
viewer_prog = g_strdup
2007
(gtk_editable_get_chars (GTK_EDITABLE (viewerbox), 0, -1));
2009
popup_errors = gtk_toggle_button_get_active
2010
(GTK_TOGGLE_BUTTON (popup_errors_box));
2013
void kkam_cleanup ()
2017
for (i = 0; i < MAX_NUMPANELS; i++)
2018
destroy_sources_list (&panels[i]);
2021
static GkrellmMonitor kam_mon =
2023
PLUGIN_NAME, /* Name, for config tab. */
2024
0, /* Id, 0 if a plugin */
2025
kkam_create_plugin, /* The create_plugin() function */
2026
kkam_update_plugin, /* The update_plugin() function */
2027
kkam_create_tab, /* The create_plugin_tab() config function */
2028
kkam_apply_config, /* The apply_plugin_config() function */
2030
kkam_save_config, /* The save_plugin_config() function */
2031
kkam_load_config, /* The load_plugin_config() function */
2032
PLUGIN_KEYWORD, /* config keyword */
2034
NULL, /* Undefined 2 */
2035
NULL, /* Undefined 1 */
2038
MON_CPU, /* Insert plugin before this monitor. */
2039
NULL, /* Handle if a plugin, filled in by GKrellM */
2040
NULL /* path if a plugin, filled in by GKrellM */
2045
__declspec(dllexport) GkrellmMonitor *
2046
gkrellm_init_plugin(win32_plugin_callbacks* calls)
2049
gkrellm_init_plugin()
2054
pGK = gkrellm_ticks();
2055
style_id = gkrellm_add_meter_style (&kam_mon, PLUGIN_STYLE);
2056
panels = g_new0 (KKamPanel, MAX_NUMPANELS);
2058
/* the g_new0 initialized everything to 0- pretty convenient for
2059
almost everything.. */
2061
for (i = 0; i < MAX_NUMPANELS; i++)
2063
panels[i].height = 50;
2064
panels[i].source = g_strdup (default_source[i]);
2065
panels[i].default_period = 60;
2068
/* gkrellm now hooks INT and QUIT and exits nicely. This will work. */
2070
g_atexit (kkam_cleanup);
2072
return (monitor = &kam_mon);