2
* Copyright (C) 1998-2006 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
28
#include "../common/inet.h"
31
#include <gtk/gtkhbbox.h>
32
#include <gtk/gtkhbox.h>
33
#include <gtk/gtklabel.h>
34
#include <gtk/gtkstock.h>
35
#include <gtk/gtkmessagedialog.h>
36
#include <gtk/gtktable.h>
37
#include <gtk/gtktreeview.h>
38
#include <gtk/gtkexpander.h>
39
#include <gtk/gtkliststore.h>
40
#include <gtk/gtktreeselection.h>
41
#include <gtk/gtkcellrendererpixbuf.h>
42
#include <gtk/gtkcellrenderertext.h>
43
#include <gtk/gtkcheckmenuitem.h>
44
#include <gtk/gtkradiobutton.h>
45
#include <gtk/gtkversion.h>
47
#include "../common/xchat.h"
48
#include "../common/xchatc.h"
49
#include "../common/fe.h"
50
#include "../common/util.h"
51
#include "../common/network.h"
57
enum /* DCC SEND/RECV */
68
COL_DCC, /* struct DCC * */
69
COL_COLOR, /* GdkColor */
80
CCOL_DCC, /* struct DCC * */
81
CCOL_COLOR, /* GdkColor * */
91
GtkTreeSelection *sel;
93
GtkWidget *abort_button;
94
GtkWidget *accept_button;
95
GtkWidget *resume_button;
96
GtkWidget *open_button;
98
GtkWidget *file_label;
99
GtkWidget *address_label;
104
struct session *sess;
110
static struct dccwindow dccfwin = {NULL, }; /* file */
111
static struct dccwindow dcccwin = {NULL, }; /* chat */
112
static GdkPixbuf *pix_up = NULL; /* down arrow */
113
static GdkPixbuf *pix_dn = NULL; /* up arrow */
114
static int win_width = 600;
115
static int win_height = 256;
116
static short view_mode; /* 1=download 2=upload 3=both */
117
#define VIEW_DOWNLOAD 1
118
#define VIEW_UPLOAD 2
121
#define KILOBYTE 1024
122
#define MEGABYTE (KILOBYTE * 1024)
123
#define GIGABYTE (MEGABYTE * 1024)
127
proper_unit (DCC_SIZE size, char *buf, int buf_len)
129
if (size <= KILOBYTE)
131
snprintf (buf, buf_len, "%"DCC_SFMT"B", size);
133
else if (size > KILOBYTE && size <= MEGABYTE)
135
snprintf (buf, buf_len, "%"DCC_SFMT"kB", size / KILOBYTE);
139
snprintf (buf, buf_len, "%.2fMB", (float)size / MEGABYTE);
144
dcc_send_filereq_file (struct my_dcc_send *mdc, char *file)
147
dcc_send (mdc->sess, mdc->nick, file, mdc->maxcps, mdc->passive);
156
fe_dcc_send_filereq (struct session *sess, char *nick, int maxcps, int passive)
159
struct my_dcc_send *mdc;
161
mdc = malloc (sizeof (*mdc));
163
mdc->nick = strdup (nick);
164
mdc->maxcps = maxcps;
165
mdc->passive = passive;
167
snprintf (tbuf, sizeof tbuf, _("Send file to %s"), nick);
168
gtkutil_file_req (tbuf, dcc_send_filereq_file, mdc, NULL, FRF_MULTIPLE);
172
dcc_prepare_row_chat (struct DCC *dcc, GtkListStore *store, GtkTreeIter *iter,
173
gboolean update_only)
175
static char pos[16], siz[16];
178
date = ctime (&dcc->starttime);
179
date[strlen (date) - 1] = 0; /* remove the \n */
181
proper_unit (dcc->pos, pos, sizeof (pos));
182
proper_unit (dcc->size, siz, sizeof (siz));
184
gtk_list_store_set (store, iter,
185
CCOL_STATUS, _(dccstat[dcc->dccstat].name),
186
CCOL_NICK, dcc->nick,
192
dccstat[dcc->dccstat].color == 1 ?
194
colors + dccstat[dcc->dccstat].color,
199
dcc_prepare_row_send (struct DCC *dcc, GtkListStore *store, GtkTreeIter *iter,
200
gboolean update_only)
202
static char pos[16], size[16], kbs[14], perc[14], eta[14];
207
pix_up = gtk_widget_render_icon (dccfwin.window, "gtk-go-up",
208
GTK_ICON_SIZE_MENU, NULL);
210
/* percentage ack'ed */
211
per = (float) ((dcc->ack * 100.00) / dcc->size);
212
proper_unit (dcc->size, size, sizeof (size));
213
proper_unit (dcc->pos, pos, sizeof (pos));
214
snprintf (kbs, sizeof (kbs), "%.1f", ((float)dcc->cps) / 1024);
215
/* proper_unit (dcc->ack, ack, sizeof (ack));*/
216
snprintf (perc, sizeof (perc), "%.0f%%", per);
219
to_go = (dcc->size - dcc->ack) / dcc->cps;
220
snprintf (eta, sizeof (eta), "%.2d:%.2d:%.2d",
221
to_go / 3600, (to_go / 60) % 60, to_go % 60);
223
strcpy (eta, "--:--:--");
226
gtk_list_store_set (store, iter,
227
COL_STATUS, _(dccstat[dcc->dccstat].name),
233
dccstat[dcc->dccstat].color == 1 ?
235
colors + dccstat[dcc->dccstat].color,
238
gtk_list_store_set (store, iter,
240
COL_STATUS, _(dccstat[dcc->dccstat].name),
241
COL_FILE, file_part (dcc->file),
250
dccstat[dcc->dccstat].color == 1 ?
252
colors + dccstat[dcc->dccstat].color,
257
dcc_prepare_row_recv (struct DCC *dcc, GtkListStore *store, GtkTreeIter *iter,
258
gboolean update_only)
260
static char size[16], pos[16], kbs[16], perc[14], eta[16];
265
pix_dn = gtk_widget_render_icon (dccfwin.window, "gtk-go-down",
266
GTK_ICON_SIZE_MENU, NULL);
268
proper_unit (dcc->size, size, sizeof (size));
269
if (dcc->dccstat == STAT_QUEUED)
270
proper_unit (dcc->resumable, pos, sizeof (pos));
272
proper_unit (dcc->pos, pos, sizeof (pos));
273
snprintf (kbs, sizeof (kbs), "%.1f", ((float)dcc->cps) / 1024);
274
/* percentage recv'ed */
275
per = (float) ((dcc->pos * 100.00) / dcc->size);
276
snprintf (perc, sizeof (perc), "%.0f%%", per);
279
to_go = (dcc->size - dcc->pos) / dcc->cps;
280
snprintf (eta, sizeof (eta), "%.2d:%.2d:%.2d",
281
to_go / 3600, (to_go / 60) % 60, to_go % 60);
283
strcpy (eta, "--:--:--");
286
gtk_list_store_set (store, iter,
287
COL_STATUS, _(dccstat[dcc->dccstat].name),
293
dccstat[dcc->dccstat].color == 1 ?
295
colors + dccstat[dcc->dccstat].color,
298
gtk_list_store_set (store, iter,
300
COL_STATUS, _(dccstat[dcc->dccstat].name),
301
COL_FILE, file_part (dcc->file),
310
dccstat[dcc->dccstat].color == 1 ?
312
colors + dccstat[dcc->dccstat].color,
317
dcc_find_row (struct DCC *find_dcc, GtkTreeModel *model, GtkTreeIter *iter, int col)
321
if (gtk_tree_model_get_iter_first (model, iter))
325
gtk_tree_model_get (model, iter, col, &dcc, -1);
329
while (gtk_tree_model_iter_next (model, iter));
336
dcc_update_recv (struct DCC *dcc)
343
if (!dcc_find_row (dcc, GTK_TREE_MODEL (dccfwin.store), &iter, COL_DCC))
346
dcc_prepare_row_recv (dcc, dccfwin.store, &iter, TRUE);
350
dcc_update_chat (struct DCC *dcc)
357
if (!dcc_find_row (dcc, GTK_TREE_MODEL (dcccwin.store), &iter, CCOL_DCC))
360
dcc_prepare_row_chat (dcc, dcccwin.store, &iter, TRUE);
364
dcc_update_send (struct DCC *dcc)
371
if (!dcc_find_row (dcc, GTK_TREE_MODEL (dccfwin.store), &iter, COL_DCC))
374
dcc_prepare_row_send (dcc, dccfwin.store, &iter, TRUE);
378
close_dcc_file_window (GtkWindow *win, gpointer data)
380
dccfwin.window = NULL;
384
dcc_append (struct DCC *dcc, GtkListStore *store, gboolean prepend)
389
gtk_list_store_prepend (store, &iter);
391
gtk_list_store_append (store, &iter);
393
if (dcc->type == TYPE_RECV)
394
dcc_prepare_row_recv (dcc, store, &iter, FALSE);
396
dcc_prepare_row_send (dcc, store, &iter, FALSE);
400
dcc_fill_window (int flags)
407
gtk_list_store_clear (GTK_LIST_STORE (dccfwin.store));
409
if (flags & VIEW_UPLOAD)
415
if (dcc->type == TYPE_SEND)
417
dcc_append (dcc, dccfwin.store, FALSE);
424
if (flags & VIEW_DOWNLOAD)
430
if (dcc->type == TYPE_RECV)
432
dcc_append (dcc, dccfwin.store, FALSE);
439
/* if only one entry, select it (so Accept button can work) */
442
gtk_tree_model_get_iter_first (GTK_TREE_MODEL (dccfwin.store), &iter);
443
gtk_tree_selection_select_iter (dccfwin.sel, &iter);
447
/* return list of selected DCCs */
450
treeview_get_selected (GtkTreeModel *model, GtkTreeSelection *sel, int column)
456
if (gtk_tree_model_get_iter_first (model, &iter))
460
if (gtk_tree_selection_iter_is_selected (sel, &iter))
462
gtk_tree_model_get (model, &iter, column, &ptr, -1);
463
list = g_slist_prepend (list, ptr);
466
while (gtk_tree_model_iter_next (model, &iter));
469
return g_slist_reverse (list);
473
dcc_get_selected (void)
475
return treeview_get_selected (GTK_TREE_MODEL (dccfwin.store),
476
dccfwin.sel, COL_DCC);
480
resume_clicked (GtkWidget * wid, gpointer none)
486
list = dcc_get_selected ();
492
if (dcc->type == TYPE_RECV && !dcc_resume (dcc))
494
switch (dcc->resume_error)
496
case 0: /* unknown error */
497
fe_message (_("That file is not resumable."), FE_MSG_ERROR);
500
snprintf (buf, sizeof (buf),
501
_( "Cannot access file: %s\n"
503
"Resuming not possible."), dcc->destfile,
504
errorstring (dcc->resume_errno));
505
fe_message (buf, FE_MSG_ERROR);
508
fe_message (_("File in download directory is larger "
509
"than file offered. Resuming not possible."), FE_MSG_ERROR);
512
fe_message (_("Cannot resume the same file from two people."), FE_MSG_ERROR);
518
abort_clicked (GtkWidget * wid, gpointer none)
521
GSList *start, *list;
523
start = list = dcc_get_selected ();
524
for (; list; list = list->next)
527
dcc_abort (dcc->serv->front_session, dcc);
529
g_slist_free (start);
533
accept_clicked (GtkWidget * wid, gpointer none)
536
GSList *start, *list;
538
start = list = dcc_get_selected ();
539
for (; list; list = list->next)
542
if (dcc->type != TYPE_SEND)
545
g_slist_free (start);
549
browse_folder (char *dir)
552
/* no need for file:// in ShellExecute() */
557
snprintf (buf, sizeof (buf), "file://%s", dir);
563
browse_dcc_folder (void)
565
if (prefs.dcc_completed_dir[0])
566
browse_folder (prefs.dcc_completed_dir);
568
browse_folder (prefs.dccdir);
572
dcc_details_populate (struct DCC *dcc)
578
gtk_label_set_text (GTK_LABEL (dccfwin.file_label), NULL);
579
gtk_label_set_text (GTK_LABEL (dccfwin.address_label), NULL);
584
if (dcc->type == TYPE_RECV)
585
gtk_label_set_text (GTK_LABEL (dccfwin.file_label), dcc->destfile);
587
gtk_label_set_text (GTK_LABEL (dccfwin.file_label), dcc->file);
589
/* address and port */
590
snprintf (buf, sizeof (buf), "%s : %d", net_ip (dcc->addr), dcc->port);
591
gtk_label_set_text (GTK_LABEL (dccfwin.address_label), buf);
595
dcc_row_cb (GtkTreeSelection *sel, gpointer user_data)
600
list = dcc_get_selected ();
603
gtk_widget_set_sensitive (dccfwin.accept_button, FALSE);
604
gtk_widget_set_sensitive (dccfwin.resume_button, FALSE);
605
gtk_widget_set_sensitive (dccfwin.abort_button, FALSE);
606
dcc_details_populate (NULL);
610
gtk_widget_set_sensitive (dccfwin.abort_button, TRUE);
612
if (list->next) /* multi selection */
614
gtk_widget_set_sensitive (dccfwin.accept_button, TRUE);
615
gtk_widget_set_sensitive (dccfwin.resume_button, TRUE);
616
dcc_details_populate (list->data);
620
/* turn OFF/ON appropriate buttons */
622
if (dcc->dccstat == STAT_QUEUED && dcc->type == TYPE_RECV)
624
gtk_widget_set_sensitive (dccfwin.accept_button, TRUE);
625
gtk_widget_set_sensitive (dccfwin.resume_button, TRUE);
629
gtk_widget_set_sensitive (dccfwin.accept_button, FALSE);
630
gtk_widget_set_sensitive (dccfwin.resume_button, FALSE);
633
dcc_details_populate (dcc);
640
dcc_dclick_cb (GtkTreeView *view, GtkTreePath *path,
641
GtkTreeViewColumn *column, gpointer data)
646
list = dcc_get_selected ();
652
if (dcc->type == TYPE_RECV)
654
accept_clicked (0, 0);
658
switch (dcc->dccstat)
663
dcc_abort (dcc->serv->front_session, dcc);
668
dcc_add_column (GtkWidget *tree, int textcol, int colorcol, char *title, gboolean right_justified)
670
GtkCellRenderer *renderer;
672
renderer = gtk_cell_renderer_text_new ();
674
g_object_set (G_OBJECT (renderer), "xalign", (float) 1.0, NULL);
675
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree), -1, title, renderer,
676
"text", textcol, "foreground-gdk", colorcol,
678
gtk_cell_renderer_text_set_fixed_height_from_font (GTK_CELL_RENDERER_TEXT (renderer), 1);
682
dcc_detail_label (char *text, GtkWidget *box, int num)
687
label = gtk_label_new (NULL);
688
snprintf (buf, sizeof (buf), "<b>%s</b>", text);
689
gtk_label_set_markup (GTK_LABEL (label), buf);
690
gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
691
gtk_table_attach (GTK_TABLE (box), label, 0, 1, 0 + num, 1 + num, GTK_FILL, GTK_FILL, 0, 0);
693
label = gtk_label_new (NULL);
694
gtk_label_set_selectable (GTK_LABEL (label), TRUE);
695
gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
696
gtk_table_attach (GTK_TABLE (box), label, 1, 2, 0 + num, 1 + num, GTK_FILL, GTK_FILL, 0, 0);
702
dcc_exp_cb (GtkWidget *exp, GtkWidget *box)
704
#if GTK_CHECK_VERSION(2,20,0)
705
if (gtk_widget_get_visible (box))
707
if (GTK_WIDGET_VISIBLE (box))
709
gtk_widget_hide (box);
711
gtk_widget_show (box);
715
dcc_toggle (GtkWidget *item, gpointer data)
717
if (GTK_TOGGLE_BUTTON (item)->active)
719
view_mode = GPOINTER_TO_INT (data);
720
dcc_fill_window (GPOINTER_TO_INT (data));
725
dcc_configure_cb (GtkWindow *win, GdkEventConfigure *event, gpointer data)
727
/* remember the window size */
728
gtk_window_get_size (win, &win_width, &win_height);
733
fe_dcc_open_recv_win (int passive)
735
GtkWidget *radio, *table, *vbox, *bbox, *view, *exp, *detailbox;
742
mg_bring_tofront (dccfwin.window);
745
dccfwin.window = mg_create_generic_tab ("Transfers", _("XChat: Uploads and Downloads"),
746
FALSE, TRUE, close_dcc_file_window, NULL,
747
win_width, win_height, &vbox, 0);
748
gtk_container_set_border_width (GTK_CONTAINER (dccfwin.window), 3);
749
gtk_box_set_spacing (GTK_BOX (vbox), 3);
751
store = gtk_list_store_new (N_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING,
752
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
753
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
754
G_TYPE_STRING, G_TYPE_POINTER, GDK_TYPE_COLOR);
755
view = gtkutil_treeview_new (vbox, GTK_TREE_MODEL (store), NULL, -1);
756
gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (view), TRUE);
757
/* Up/Down Icon column */
758
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (view), -1, NULL,
759
gtk_cell_renderer_pixbuf_new (),
760
"pixbuf", COL_TYPE, NULL);
761
dcc_add_column (view, COL_STATUS, COL_COLOR, _("Status"), FALSE);
762
dcc_add_column (view, COL_FILE, COL_COLOR, _("File"), FALSE);
763
dcc_add_column (view, COL_SIZE, COL_COLOR, _("Size"), TRUE);
764
dcc_add_column (view, COL_POS, COL_COLOR, _("Position"), TRUE);
765
dcc_add_column (view, COL_PERC, COL_COLOR, "%", TRUE);
766
dcc_add_column (view, COL_SPEED, COL_COLOR, "KB/s", TRUE);
767
dcc_add_column (view, COL_ETA, COL_COLOR, _("ETA"), FALSE);
768
dcc_add_column (view, COL_NICK, COL_COLOR, _("Nick"), FALSE);
770
gtk_tree_view_column_set_expand (gtk_tree_view_get_column (GTK_TREE_VIEW (view), COL_FILE), TRUE);
771
gtk_tree_view_column_set_expand (gtk_tree_view_get_column (GTK_TREE_VIEW (view), COL_NICK), TRUE);
774
dccfwin.store = store;
775
dccfwin.sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (view));
776
view_mode = VIEW_BOTH;
777
gtk_tree_selection_set_mode (dccfwin.sel, GTK_SELECTION_MULTIPLE);
779
if (!prefs.windows_as_tabs)
780
g_signal_connect (G_OBJECT (dccfwin.window), "configure_event",
781
G_CALLBACK (dcc_configure_cb), 0);
782
g_signal_connect (G_OBJECT (dccfwin.sel), "changed",
783
G_CALLBACK (dcc_row_cb), NULL);
785
g_signal_connect (G_OBJECT (view), "row-activated",
786
G_CALLBACK (dcc_dclick_cb), NULL);
788
table = gtk_table_new (1, 3, FALSE);
789
gtk_table_set_col_spacings (GTK_TABLE (table), 16);
790
gtk_box_pack_start (GTK_BOX (vbox), table, 0, 0, 0);
792
radio = gtk_radio_button_new_with_mnemonic (NULL, _("Both"));
793
g_signal_connect (G_OBJECT (radio), "toggled",
794
G_CALLBACK (dcc_toggle), GINT_TO_POINTER (VIEW_BOTH));
795
gtk_table_attach (GTK_TABLE (table), radio, 3, 4, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
796
group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio));
798
radio = gtk_radio_button_new_with_mnemonic (group, _("Uploads"));
799
g_signal_connect (G_OBJECT (radio), "toggled",
800
G_CALLBACK (dcc_toggle), GINT_TO_POINTER (VIEW_UPLOAD));
801
gtk_table_attach (GTK_TABLE (table), radio, 1, 2, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
802
group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio));
804
radio = gtk_radio_button_new_with_mnemonic (group, _("Downloads"));
805
g_signal_connect (G_OBJECT (radio), "toggled",
806
G_CALLBACK (dcc_toggle), GINT_TO_POINTER (VIEW_DOWNLOAD));
807
gtk_table_attach (GTK_TABLE (table), radio, 2, 3, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
809
exp = gtk_expander_new (_("Details"));
810
gtk_table_attach (GTK_TABLE (table), exp, 0, 1, 0, 1, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
812
detailbox = gtk_table_new (3, 3, FALSE);
813
gtk_table_set_col_spacings (GTK_TABLE (detailbox), 6);
814
gtk_table_set_row_spacings (GTK_TABLE (detailbox), 2);
815
gtk_container_set_border_width (GTK_CONTAINER (detailbox), 6);
816
g_signal_connect (G_OBJECT (exp), "activate",
817
G_CALLBACK (dcc_exp_cb), detailbox);
818
gtk_table_attach (GTK_TABLE (table), detailbox, 0, 4, 1, 2, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
820
dccfwin.file_label = dcc_detail_label (_("File:"), detailbox, 0);
821
dccfwin.address_label = dcc_detail_label (_("Address:"), detailbox, 1);
823
bbox = gtk_hbutton_box_new ();
824
gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_SPREAD);
825
gtk_box_pack_end (GTK_BOX (vbox), bbox, FALSE, FALSE, 2);
827
dccfwin.abort_button = gtkutil_button (bbox, GTK_STOCK_CANCEL, 0, abort_clicked, 0, _("Abort"));
828
dccfwin.accept_button = gtkutil_button (bbox, GTK_STOCK_APPLY, 0, accept_clicked, 0, _("Accept"));
829
dccfwin.resume_button = gtkutil_button (bbox, GTK_STOCK_REFRESH, 0, resume_clicked, 0, _("Resume"));
830
dccfwin.open_button = gtkutil_button (bbox, 0, 0, browse_dcc_folder, 0, _("Open Folder..."));
831
gtk_widget_set_sensitive (dccfwin.accept_button, FALSE);
832
gtk_widget_set_sensitive (dccfwin.resume_button, FALSE);
833
gtk_widget_set_sensitive (dccfwin.abort_button, FALSE);
836
gtk_widget_show_all (dccfwin.window);
837
gtk_widget_hide (detailbox);
843
fe_dcc_open_send_win (int passive)
845
/* combined send/recv GUI */
846
return fe_dcc_open_recv_win (passive);
850
/* DCC CHAT GUIs BELOW */
853
dcc_chat_get_selected (void)
855
return treeview_get_selected (GTK_TREE_MODEL (dcccwin.store),
856
dcccwin.sel, CCOL_DCC);
860
accept_chat_clicked (GtkWidget * wid, gpointer none)
863
GSList *start, *list;
865
start = list = dcc_chat_get_selected ();
866
for (; list; list = list->next)
871
g_slist_free (start);
875
abort_chat_clicked (GtkWidget * wid, gpointer none)
878
GSList *start, *list;
880
start = list = dcc_chat_get_selected ();
881
for (; list; list = list->next)
884
dcc_abort (dcc->serv->front_session, dcc);
886
g_slist_free (start);
890
dcc_chat_close_cb (void)
892
dcccwin.window = NULL;
896
dcc_chat_append (struct DCC *dcc, GtkListStore *store, gboolean prepend)
901
gtk_list_store_prepend (store, &iter);
903
gtk_list_store_append (store, &iter);
905
dcc_prepare_row_chat (dcc, store, &iter, FALSE);
909
dcc_chat_fill_win (void)
916
gtk_list_store_clear (GTK_LIST_STORE (dcccwin.store));
922
if (dcc->type == TYPE_CHATSEND || dcc->type == TYPE_CHATRECV)
924
dcc_chat_append (dcc, dcccwin.store, FALSE);
930
/* if only one entry, select it (so Accept button can work) */
933
gtk_tree_model_get_iter_first (GTK_TREE_MODEL (dcccwin.store), &iter);
934
gtk_tree_selection_select_iter (dcccwin.sel, &iter);
939
dcc_chat_row_cb (GtkTreeSelection *sel, gpointer user_data)
944
list = dcc_chat_get_selected ();
947
gtk_widget_set_sensitive (dcccwin.accept_button, FALSE);
948
gtk_widget_set_sensitive (dcccwin.abort_button, FALSE);
952
gtk_widget_set_sensitive (dcccwin.abort_button, TRUE);
954
if (list->next) /* multi selection */
955
gtk_widget_set_sensitive (dcccwin.accept_button, TRUE);
958
/* turn OFF/ON appropriate buttons */
960
if (dcc->dccstat == STAT_QUEUED && dcc->type == TYPE_CHATRECV)
961
gtk_widget_set_sensitive (dcccwin.accept_button, TRUE);
963
gtk_widget_set_sensitive (dcccwin.accept_button, FALSE);
970
dcc_chat_dclick_cb (GtkTreeView *view, GtkTreePath *path,
971
GtkTreeViewColumn *column, gpointer data)
973
accept_chat_clicked (0, 0);
977
fe_dcc_open_chat_win (int passive)
979
GtkWidget *view, *vbox, *bbox;
985
mg_bring_tofront (dcccwin.window);
990
mg_create_generic_tab ("DCCChat", _("XChat: DCC Chat List"),
991
FALSE, TRUE, dcc_chat_close_cb, NULL, 550, 180, &vbox, 0);
992
gtk_container_set_border_width (GTK_CONTAINER (dcccwin.window), 3);
993
gtk_box_set_spacing (GTK_BOX (vbox), 3);
995
store = gtk_list_store_new (CN_COLUMNS, G_TYPE_STRING, G_TYPE_STRING,
996
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
997
G_TYPE_POINTER, GDK_TYPE_COLOR);
998
view = gtkutil_treeview_new (vbox, GTK_TREE_MODEL (store), NULL, -1);
1000
dcc_add_column (view, CCOL_STATUS, CCOL_COLOR, _("Status"), FALSE);
1001
dcc_add_column (view, CCOL_NICK, CCOL_COLOR, _("Nick"), FALSE);
1002
dcc_add_column (view, CCOL_RECV, CCOL_COLOR, _("Recv"), TRUE);
1003
dcc_add_column (view, CCOL_SENT, CCOL_COLOR, _("Sent"), TRUE);
1004
dcc_add_column (view, CCOL_START, CCOL_COLOR, _("Start Time"), FALSE);
1006
gtk_tree_view_column_set_expand (gtk_tree_view_get_column (GTK_TREE_VIEW (view), 1), TRUE);
1007
gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (view), TRUE);
1009
dcccwin.list = view;
1010
dcccwin.store = store;
1011
dcccwin.sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (view));
1012
gtk_tree_selection_set_mode (dcccwin.sel, GTK_SELECTION_MULTIPLE);
1014
g_signal_connect (G_OBJECT (dcccwin.sel), "changed",
1015
G_CALLBACK (dcc_chat_row_cb), NULL);
1017
g_signal_connect (G_OBJECT (view), "row-activated",
1018
G_CALLBACK (dcc_chat_dclick_cb), NULL);
1020
bbox = gtk_hbutton_box_new ();
1021
gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_SPREAD);
1022
gtk_box_pack_end (GTK_BOX (vbox), bbox, FALSE, FALSE, 2);
1024
dcccwin.abort_button = gtkutil_button (bbox, GTK_STOCK_CANCEL, 0, abort_chat_clicked, 0, _("Abort"));
1025
dcccwin.accept_button = gtkutil_button (bbox, GTK_STOCK_APPLY, 0, accept_chat_clicked, 0, _("Accept"));
1026
gtk_widget_set_sensitive (dcccwin.accept_button, FALSE);
1027
gtk_widget_set_sensitive (dcccwin.abort_button, FALSE);
1029
dcc_chat_fill_win ();
1030
gtk_widget_show_all (dcccwin.window);
1036
fe_dcc_add (struct DCC *dcc)
1041
if (dccfwin.window && (view_mode & VIEW_DOWNLOAD))
1042
dcc_append (dcc, dccfwin.store, TRUE);
1046
if (dccfwin.window && (view_mode & VIEW_UPLOAD))
1047
dcc_append (dcc, dccfwin.store, TRUE);
1052
dcc_chat_append (dcc, dcccwin.store, TRUE);
1057
fe_dcc_update (struct DCC *dcc)
1062
dcc_update_send (dcc);
1066
dcc_update_recv (dcc);
1070
dcc_update_chat (dcc);
1075
fe_dcc_remove (struct DCC *dcc)
1085
if (dcc_find_row (dcc, GTK_TREE_MODEL (dccfwin.store), &iter, COL_DCC))
1086
gtk_list_store_remove (dccfwin.store, &iter);
1093
if (dcc_find_row (dcc, GTK_TREE_MODEL (dcccwin.store), &iter, CCOL_DCC))
1094
gtk_list_store_remove (dcccwin.store, &iter);