fix implicit declarations
[rofl0r-ixchat.git] / src / fe-gtk / notifygui.c
blob83a9b5725a30d958e808f9930069d7de55c3de88
1 /* X-Chat
2 * Copyright (C) 1998 Peter Zelezny.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <fcntl.h>
23 #include <time.h>
25 #include "fe-gtk.h"
27 #include <gtk/gtkhbox.h>
28 #include <gtk/gtkstock.h>
29 #include <gtk/gtkhbbox.h>
30 #include <gtk/gtkscrolledwindow.h>
32 #include <gtk/gtklabel.h>
33 #include <gtk/gtkliststore.h>
34 #include <gtk/gtkentry.h>
35 #include <gtk/gtkmessagedialog.h>
36 #include <gtk/gtktable.h>
37 #include <gtk/gtktreeview.h>
38 #include <gtk/gtktreeselection.h>
39 #include <gtk/gtkcellrenderertext.h>
41 #include "../common/xchat.h"
42 #include "../common/notify.h"
43 #include "../common/cfgfiles.h"
44 #include "../common/fe.h"
45 #include "../common/server.h"
46 #include "../common/util.h"
47 #include "../common/userlist.h"
48 #include "../common/outbound.h"
49 #include "gtkutil.h"
50 #include "maingui.h"
51 #include "palette.h"
52 #include "notifygui.h"
55 /* model for the notify treeview */
56 enum
58 USER_COLUMN,
59 STATUS_COLUMN,
60 SERVER_COLUMN,
61 SEEN_COLUMN,
62 COLOUR_COLUMN,
63 NPS_COLUMN, /* struct notify_per_server * */
64 N_COLUMNS
68 static GtkWidget *notify_window = 0;
69 static GtkWidget *notify_button_opendialog;
70 static GtkWidget *notify_button_remove;
73 static void
74 notify_closegui (void)
76 notify_window = 0;
79 /* Need this to be able to set the foreground colour property of a row
80 * from a GdkColor * in the model -Vince
82 static void
83 notify_treecell_property_mapper (GtkTreeViewColumn *col, GtkCellRenderer *cell,
84 GtkTreeModel *model, GtkTreeIter *iter,
85 gpointer data)
87 gchar *text;
88 GdkColor *colour;
89 int model_column = GPOINTER_TO_INT (data);
91 gtk_tree_model_get (GTK_TREE_MODEL (model), iter,
92 COLOUR_COLUMN, &colour,
93 model_column, &text, -1);
94 g_object_set (G_OBJECT (cell), "text", text, NULL);
95 g_object_set (G_OBJECT (cell), "foreground-gdk", colour, NULL);
96 g_free (text);
99 static void
100 notify_row_cb (GtkTreeSelection *sel, GtkTreeView *view)
102 GtkTreeIter iter;
103 struct notify_per_server *servnot;
105 if (gtkutil_treeview_get_selected (view, &iter, NPS_COLUMN, &servnot, -1))
107 gtk_widget_set_sensitive (notify_button_opendialog, servnot ? servnot->ison : 0);
108 gtk_widget_set_sensitive (notify_button_remove, TRUE);
109 return;
112 gtk_widget_set_sensitive (notify_button_opendialog, FALSE);
113 gtk_widget_set_sensitive (notify_button_remove, FALSE);
116 static GtkWidget *
117 notify_treeview_new (GtkWidget *box)
119 GtkListStore *store;
120 GtkWidget *view;
121 GtkTreeViewColumn *col;
122 int col_id;
124 store = gtk_list_store_new (N_COLUMNS,
125 G_TYPE_STRING,
126 G_TYPE_STRING,
127 G_TYPE_STRING,
128 G_TYPE_STRING,
129 G_TYPE_POINTER, /* can't specify colour! */
130 G_TYPE_POINTER
132 g_return_val_if_fail (store != NULL, NULL);
134 view = gtkutil_treeview_new (box, GTK_TREE_MODEL (store),
135 notify_treecell_property_mapper,
136 USER_COLUMN, _("Name"),
137 STATUS_COLUMN, _("Status"),
138 SERVER_COLUMN, _("Network"),
139 SEEN_COLUMN, _("Last Seen"), -1);
140 gtk_tree_view_column_set_expand (gtk_tree_view_get_column (GTK_TREE_VIEW (view), 0), TRUE);
142 for (col_id=0; (col = gtk_tree_view_get_column (GTK_TREE_VIEW (view), col_id));
143 col_id++)
144 gtk_tree_view_column_set_alignment (col, 0.5);
146 g_signal_connect (G_OBJECT (gtk_tree_view_get_selection (GTK_TREE_VIEW (view))),
147 "changed", G_CALLBACK (notify_row_cb), view);
149 gtk_widget_show (view);
150 return view;
153 void
154 notify_gui_update (void)
156 struct notify *notify;
157 struct notify_per_server *servnot;
158 GSList *list = notify_list;
159 GSList *slist;
160 gchar *name, *status, *server, *seen;
161 int online, servcount;
162 time_t lastseen;
163 char agobuf[128];
165 GtkListStore *store;
166 GtkTreeView *view;
167 GtkTreeIter iter;
168 gboolean valid; /* true if we don't need to append a new tree row */
170 if (!notify_window)
171 return;
173 view = g_object_get_data (G_OBJECT (notify_window), "view");
174 store = GTK_LIST_STORE (gtk_tree_view_get_model (view));
175 valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter);
177 while (list)
179 notify = (struct notify *) list->data;
180 name = notify->name;
181 status = _("Offline");
182 server = "";
184 online = FALSE;
185 lastseen = 0;
186 /* First see if they're online on any servers */
187 slist = notify->server_list;
188 while (slist)
190 servnot = (struct notify_per_server *) slist->data;
191 if (servnot->ison)
192 online = TRUE;
193 if (servnot->lastseen > lastseen)
194 lastseen = servnot->lastseen;
195 slist = slist->next;
198 if (!online) /* Offline on all servers */
200 if (!lastseen)
201 seen = _("Never");
202 else
204 snprintf (agobuf, sizeof (agobuf), _("%d minutes ago"), (int)(time (0) - lastseen) / 60);
205 seen = agobuf;
207 if (!valid) /* create new tree row if required */
208 gtk_list_store_append (store, &iter);
209 gtk_list_store_set (store, &iter, 0, name, 1, status,
210 2, server, 3, seen, 4, &colors[4], 5, NULL, -1);
211 if (valid)
212 valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter);
214 } else
216 /* Online - add one line per server */
217 servcount = 0;
218 slist = notify->server_list;
219 status = _("Online");
220 while (slist)
222 servnot = (struct notify_per_server *) slist->data;
223 if (servnot->ison)
225 if (servcount > 0)
226 name = "";
227 server = server_get_network (servnot->server, TRUE);
229 snprintf (agobuf, sizeof (agobuf), _("%d minutes ago"), (int)(time (0) - lastseen) / 60);
230 seen = agobuf;
232 if (!valid) /* create new tree row if required */
233 gtk_list_store_append (store, &iter);
234 gtk_list_store_set (store, &iter, 0, name, 1, status,
235 2, server, 3, seen, 4, &colors[3], 5, servnot, -1);
236 if (valid)
237 valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter);
239 servcount++;
241 slist = slist->next;
245 list = list->next;
248 while (valid)
250 GtkTreeIter old = iter;
251 /* get next iter now because removing invalidates old one */
252 valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (store),
253 &iter);
254 gtk_list_store_remove (store, &old);
258 static void
259 notify_opendialog_clicked (GtkWidget * igad)
261 GtkTreeView *view;
262 GtkTreeIter iter;
263 struct notify_per_server *servnot;
265 view = g_object_get_data (G_OBJECT (notify_window), "view");
266 if (gtkutil_treeview_get_selected (view, &iter, NPS_COLUMN, &servnot, -1))
268 if (servnot)
269 open_query (servnot->server, servnot->notify->name, TRUE);
273 static void
274 notify_remove_clicked (GtkWidget * igad)
276 GtkTreeView *view;
277 GtkTreeModel *model;
278 GtkTreeIter iter;
279 GtkTreePath *path = NULL;
280 gboolean found = FALSE;
281 char *name;
283 view = g_object_get_data (G_OBJECT (notify_window), "view");
284 if (gtkutil_treeview_get_selected (view, &iter, USER_COLUMN, &name, -1))
286 model = gtk_tree_view_get_model (view);
287 found = (*name != 0);
288 while (!found) /* the real nick is some previous node */
290 g_free (name); /* it's useless to us */
291 if (!path)
292 path = gtk_tree_model_get_path (model, &iter);
293 if (!gtk_tree_path_prev (path)) /* arrgh! no previous node! */
295 g_warning ("notify list state is invalid\n");
296 break;
298 if (!gtk_tree_model_get_iter (model, &iter, path))
299 break;
300 gtk_tree_model_get (model, &iter, USER_COLUMN, &name, -1);
301 found = (*name != 0);
303 if (path)
304 gtk_tree_path_free (path);
305 if (!found)
306 return;
308 /* ok, now we can remove it */
309 gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
310 notify_deluser (name);
311 g_free (name);
315 static void
316 notifygui_add_cb (GtkDialog *dialog, gint response, gpointer entry)
318 char *networks;
319 char *text;
321 text = GTK_ENTRY (entry)->text;
322 if (text[0] && response == GTK_RESPONSE_ACCEPT)
324 networks = GTK_ENTRY (g_object_get_data (G_OBJECT (entry), "net"))->text;
325 if (strcasecmp (networks, "ALL") == 0 || networks[0] == 0)
326 notify_adduser (text, NULL);
327 else
328 notify_adduser (text, networks);
331 gtk_widget_destroy (GTK_WIDGET (dialog));
334 static void
335 notifygui_add_enter (GtkWidget *entry, GtkWidget *dialog)
337 gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
340 void
341 fe_notify_ask (char *nick, char *networks)
343 GtkWidget *dialog;
344 GtkWidget *entry;
345 GtkWidget *label;
346 GtkWidget *wid;
347 GtkWidget *table;
348 char *msg = _("Enter nickname to add:");
349 char buf[256];
351 dialog = gtk_dialog_new_with_buttons (msg, NULL, 0,
352 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
353 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
354 NULL);
355 if (parent_window)
356 gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (parent_window));
357 gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
359 table = gtk_table_new (2, 3, FALSE);
360 gtk_container_set_border_width (GTK_CONTAINER (table), 12);
361 gtk_table_set_row_spacings (GTK_TABLE (table), 3);
362 gtk_table_set_col_spacings (GTK_TABLE (table), 8);
363 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), table);
365 label = gtk_label_new (msg);
366 gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 0, 1);
368 entry = gtk_entry_new ();
369 gtk_entry_set_text (GTK_ENTRY (entry), nick);
370 g_signal_connect (G_OBJECT (entry), "activate",
371 G_CALLBACK (notifygui_add_enter), dialog);
372 gtk_table_attach_defaults (GTK_TABLE (table), entry, 1, 2, 0, 1);
374 g_signal_connect (G_OBJECT (dialog), "response",
375 G_CALLBACK (notifygui_add_cb), entry);
377 label = gtk_label_new (_("Notify on these networks:"));
378 gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 2, 3);
380 wid = gtk_entry_new ();
381 g_object_set_data (G_OBJECT (entry), "net", wid);
382 g_signal_connect (G_OBJECT (wid), "activate",
383 G_CALLBACK (notifygui_add_enter), dialog);
384 gtk_entry_set_text (GTK_ENTRY (wid), networks ? networks : "ALL");
385 gtk_table_attach_defaults (GTK_TABLE (table), wid, 1, 2, 2, 3);
387 label = gtk_label_new (NULL);
388 snprintf (buf, sizeof (buf), "<i><span size=\"smaller\">%s</span></i>", _("Comma separated list of networks is accepted."));
389 gtk_label_set_markup (GTK_LABEL (label), buf);
390 gtk_table_attach_defaults (GTK_TABLE (table), label, 1, 2, 3, 4);
392 gtk_widget_show_all (dialog);
395 static void
396 notify_add_clicked (GtkWidget * igad)
398 fe_notify_ask ("", NULL);
401 void
402 notify_opengui (void)
404 GtkWidget *vbox, *bbox;
405 GtkWidget *view;
407 if (notify_window)
409 mg_bring_tofront (notify_window);
410 return;
413 notify_window =
414 mg_create_generic_tab ("Notify", _("XChat: Friends List"), FALSE, TRUE,
415 notify_closegui, NULL, 400, 250, &vbox, 0);
417 view = notify_treeview_new (vbox);
418 g_object_set_data (G_OBJECT (notify_window), "view", view);
420 bbox = gtk_hbutton_box_new ();
421 gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_SPREAD);
422 gtk_container_set_border_width (GTK_CONTAINER (bbox), 5);
423 gtk_box_pack_end (GTK_BOX (vbox), bbox, 0, 0, 0);
424 gtk_widget_show (bbox);
426 gtkutil_button (bbox, GTK_STOCK_NEW, 0, notify_add_clicked, 0,
427 _("Add..."));
429 notify_button_remove =
430 gtkutil_button (bbox, GTK_STOCK_DELETE, 0, notify_remove_clicked, 0,
431 _("Remove"));
433 notify_button_opendialog =
434 gtkutil_button (bbox, NULL, 0, notify_opendialog_clicked, 0,
435 _("Open Dialog"));
437 gtk_widget_set_sensitive (notify_button_opendialog, FALSE);
438 gtk_widget_set_sensitive (notify_button_remove, FALSE);
440 notify_gui_update ();
442 gtk_widget_show (notify_window);