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
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"
52 #include "notifygui.h"
55 /* model for the notify treeview */
63 NPS_COLUMN
, /* struct notify_per_server * */
68 static GtkWidget
*notify_window
= 0;
69 static GtkWidget
*notify_button_opendialog
;
70 static GtkWidget
*notify_button_remove
;
74 notify_closegui (void)
79 /* Need this to be able to set the foreground colour property of a row
80 * from a GdkColor * in the model -Vince
83 notify_treecell_property_mapper (GtkTreeViewColumn
*col
, GtkCellRenderer
*cell
,
84 GtkTreeModel
*model
, GtkTreeIter
*iter
,
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
);
100 notify_row_cb (GtkTreeSelection
*sel
, GtkTreeView
*view
)
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
);
112 gtk_widget_set_sensitive (notify_button_opendialog
, FALSE
);
113 gtk_widget_set_sensitive (notify_button_remove
, FALSE
);
117 notify_treeview_new (GtkWidget
*box
)
121 GtkTreeViewColumn
*col
;
124 store
= gtk_list_store_new (N_COLUMNS
,
129 G_TYPE_POINTER
, /* can't specify colour! */
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
));
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
);
154 notify_gui_update (void)
156 struct notify
*notify
;
157 struct notify_per_server
*servnot
;
158 GSList
*list
= notify_list
;
160 gchar
*name
, *status
, *server
, *seen
;
161 int online
, servcount
;
168 gboolean valid
; /* true if we don't need to append a new tree row */
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
);
179 notify
= (struct notify
*) list
->data
;
181 status
= _("Offline");
186 /* First see if they're online on any servers */
187 slist
= notify
->server_list
;
190 servnot
= (struct notify_per_server
*) slist
->data
;
193 if (servnot
->lastseen
> lastseen
)
194 lastseen
= servnot
->lastseen
;
198 if (!online
) /* Offline on all servers */
204 snprintf (agobuf
, sizeof (agobuf
), _("%d minutes ago"), (int)(time (0) - lastseen
) / 60);
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);
212 valid
= gtk_tree_model_iter_next (GTK_TREE_MODEL (store
), &iter
);
216 /* Online - add one line per server */
218 slist
= notify
->server_list
;
219 status
= _("Online");
222 servnot
= (struct notify_per_server
*) slist
->data
;
227 server
= server_get_network (servnot
->server
, TRUE
);
229 snprintf (agobuf
, sizeof (agobuf
), _("%d minutes ago"), (int)(time (0) - lastseen
) / 60);
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);
237 valid
= gtk_tree_model_iter_next (GTK_TREE_MODEL (store
), &iter
);
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
),
254 gtk_list_store_remove (store
, &old
);
259 notify_opendialog_clicked (GtkWidget
* igad
)
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))
269 open_query (servnot
->server
, servnot
->notify
->name
, TRUE
);
274 notify_remove_clicked (GtkWidget
* igad
)
279 GtkTreePath
*path
= NULL
;
280 gboolean found
= FALSE
;
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 */
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");
298 if (!gtk_tree_model_get_iter (model
, &iter
, path
))
300 gtk_tree_model_get (model
, &iter
, USER_COLUMN
, &name
, -1);
301 found
= (*name
!= 0);
304 gtk_tree_path_free (path
);
308 /* ok, now we can remove it */
309 gtk_list_store_remove (GTK_LIST_STORE (model
), &iter
);
310 notify_deluser (name
);
316 notifygui_add_cb (GtkDialog
*dialog
, gint response
, gpointer entry
)
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
);
328 notify_adduser (text
, networks
);
331 gtk_widget_destroy (GTK_WIDGET (dialog
));
335 notifygui_add_enter (GtkWidget
*entry
, GtkWidget
*dialog
)
337 gtk_dialog_response (GTK_DIALOG (dialog
), GTK_RESPONSE_ACCEPT
);
341 fe_notify_ask (char *nick
, char *networks
)
348 char *msg
= _("Enter nickname to add:");
351 dialog
= gtk_dialog_new_with_buttons (msg
, NULL
, 0,
352 GTK_STOCK_CANCEL
, GTK_RESPONSE_REJECT
,
353 GTK_STOCK_OK
, GTK_RESPONSE_ACCEPT
,
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
);
396 notify_add_clicked (GtkWidget
* igad
)
398 fe_notify_ask ("", NULL
);
402 notify_opengui (void)
404 GtkWidget
*vbox
, *bbox
;
409 mg_bring_tofront (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,
429 notify_button_remove
=
430 gtkutil_button (bbox
, GTK_STOCK_DELETE
, 0, notify_remove_clicked
, 0,
433 notify_button_opendialog
=
434 gtkutil_button (bbox
, NULL
, 0, notify_opendialog_clicked
, 0,
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
);