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
)
553 snprintf (buf
, sizeof (buf
), "file://%s", dir
);
558 browse_dcc_folder (void)
560 if (prefs
.dcc_completed_dir
[0])
561 browse_folder (prefs
.dcc_completed_dir
);
563 browse_folder (prefs
.dccdir
);
567 dcc_details_populate (struct DCC
*dcc
)
573 gtk_label_set_text (GTK_LABEL (dccfwin
.file_label
), NULL
);
574 gtk_label_set_text (GTK_LABEL (dccfwin
.address_label
), NULL
);
579 if (dcc
->type
== TYPE_RECV
)
580 gtk_label_set_text (GTK_LABEL (dccfwin
.file_label
), dcc
->destfile
);
582 gtk_label_set_text (GTK_LABEL (dccfwin
.file_label
), dcc
->file
);
584 /* address and port */
585 snprintf (buf
, sizeof (buf
), "%s : %d", net_ip (dcc
->addr
), dcc
->port
);
586 gtk_label_set_text (GTK_LABEL (dccfwin
.address_label
), buf
);
590 dcc_row_cb (GtkTreeSelection
*sel
, gpointer user_data
)
595 list
= dcc_get_selected ();
598 gtk_widget_set_sensitive (dccfwin
.accept_button
, FALSE
);
599 gtk_widget_set_sensitive (dccfwin
.resume_button
, FALSE
);
600 gtk_widget_set_sensitive (dccfwin
.abort_button
, FALSE
);
601 dcc_details_populate (NULL
);
605 gtk_widget_set_sensitive (dccfwin
.abort_button
, TRUE
);
607 if (list
->next
) /* multi selection */
609 gtk_widget_set_sensitive (dccfwin
.accept_button
, TRUE
);
610 gtk_widget_set_sensitive (dccfwin
.resume_button
, TRUE
);
611 dcc_details_populate (list
->data
);
615 /* turn OFF/ON appropriate buttons */
617 if (dcc
->dccstat
== STAT_QUEUED
&& dcc
->type
== TYPE_RECV
)
619 gtk_widget_set_sensitive (dccfwin
.accept_button
, TRUE
);
620 gtk_widget_set_sensitive (dccfwin
.resume_button
, TRUE
);
624 gtk_widget_set_sensitive (dccfwin
.accept_button
, FALSE
);
625 gtk_widget_set_sensitive (dccfwin
.resume_button
, FALSE
);
628 dcc_details_populate (dcc
);
635 dcc_dclick_cb (GtkTreeView
*view
, GtkTreePath
*path
,
636 GtkTreeViewColumn
*column
, gpointer data
)
641 list
= dcc_get_selected ();
647 if (dcc
->type
== TYPE_RECV
)
649 accept_clicked (0, 0);
653 switch (dcc
->dccstat
)
658 dcc_abort (dcc
->serv
->front_session
, dcc
);
663 dcc_add_column (GtkWidget
*tree
, int textcol
, int colorcol
, char *title
, gboolean right_justified
)
665 GtkCellRenderer
*renderer
;
667 renderer
= gtk_cell_renderer_text_new ();
669 g_object_set (G_OBJECT (renderer
), "xalign", (float) 1.0, NULL
);
670 gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree
), -1, title
, renderer
,
671 "text", textcol
, "foreground-gdk", colorcol
,
673 gtk_cell_renderer_text_set_fixed_height_from_font (GTK_CELL_RENDERER_TEXT (renderer
), 1);
677 dcc_detail_label (char *text
, GtkWidget
*box
, int num
)
682 label
= gtk_label_new (NULL
);
683 snprintf (buf
, sizeof (buf
), "<b>%s</b>", text
);
684 gtk_label_set_markup (GTK_LABEL (label
), buf
);
685 gtk_misc_set_alignment (GTK_MISC (label
), 0, 0);
686 gtk_table_attach (GTK_TABLE (box
), label
, 0, 1, 0 + num
, 1 + num
, GTK_FILL
, GTK_FILL
, 0, 0);
688 label
= gtk_label_new (NULL
);
689 gtk_label_set_selectable (GTK_LABEL (label
), TRUE
);
690 gtk_misc_set_alignment (GTK_MISC (label
), 0, 0);
691 gtk_table_attach (GTK_TABLE (box
), label
, 1, 2, 0 + num
, 1 + num
, GTK_FILL
, GTK_FILL
, 0, 0);
697 dcc_exp_cb (GtkWidget
*exp
, GtkWidget
*box
)
699 #if GTK_CHECK_VERSION(2,20,0)
700 if (gtk_widget_get_visible (box
))
702 if (GTK_WIDGET_VISIBLE (box
))
704 gtk_widget_hide (box
);
706 gtk_widget_show (box
);
710 dcc_toggle (GtkWidget
*item
, gpointer data
)
712 if (GTK_TOGGLE_BUTTON (item
)->active
)
714 view_mode
= GPOINTER_TO_INT (data
);
715 dcc_fill_window (GPOINTER_TO_INT (data
));
720 dcc_configure_cb (GtkWindow
*win
, GdkEventConfigure
*event
, gpointer data
)
722 /* remember the window size */
723 gtk_window_get_size (win
, &win_width
, &win_height
);
728 fe_dcc_open_recv_win (int passive
)
730 GtkWidget
*radio
, *table
, *vbox
, *bbox
, *view
, *exp
, *detailbox
;
737 mg_bring_tofront (dccfwin
.window
);
740 dccfwin
.window
= mg_create_generic_tab ("Transfers", _("XChat: Uploads and Downloads"),
741 FALSE
, TRUE
, close_dcc_file_window
, NULL
,
742 win_width
, win_height
, &vbox
, 0);
743 gtk_container_set_border_width (GTK_CONTAINER (dccfwin
.window
), 3);
744 gtk_box_set_spacing (GTK_BOX (vbox
), 3);
746 store
= gtk_list_store_new (N_COLUMNS
, GDK_TYPE_PIXBUF
, G_TYPE_STRING
,
747 G_TYPE_STRING
, G_TYPE_STRING
, G_TYPE_STRING
,
748 G_TYPE_STRING
, G_TYPE_STRING
, G_TYPE_STRING
,
749 G_TYPE_STRING
, G_TYPE_POINTER
, GDK_TYPE_COLOR
);
750 view
= gtkutil_treeview_new (vbox
, GTK_TREE_MODEL (store
), NULL
, -1);
751 gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (view
), TRUE
);
752 /* Up/Down Icon column */
753 gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (view
), -1, NULL
,
754 gtk_cell_renderer_pixbuf_new (),
755 "pixbuf", COL_TYPE
, NULL
);
756 dcc_add_column (view
, COL_STATUS
, COL_COLOR
, _("Status"), FALSE
);
757 dcc_add_column (view
, COL_FILE
, COL_COLOR
, _("File"), FALSE
);
758 dcc_add_column (view
, COL_SIZE
, COL_COLOR
, _("Size"), TRUE
);
759 dcc_add_column (view
, COL_POS
, COL_COLOR
, _("Position"), TRUE
);
760 dcc_add_column (view
, COL_PERC
, COL_COLOR
, "%", TRUE
);
761 dcc_add_column (view
, COL_SPEED
, COL_COLOR
, "KB/s", TRUE
);
762 dcc_add_column (view
, COL_ETA
, COL_COLOR
, _("ETA"), FALSE
);
763 dcc_add_column (view
, COL_NICK
, COL_COLOR
, _("Nick"), FALSE
);
765 gtk_tree_view_column_set_expand (gtk_tree_view_get_column (GTK_TREE_VIEW (view
), COL_FILE
), TRUE
);
766 gtk_tree_view_column_set_expand (gtk_tree_view_get_column (GTK_TREE_VIEW (view
), COL_NICK
), TRUE
);
769 dccfwin
.store
= store
;
770 dccfwin
.sel
= gtk_tree_view_get_selection (GTK_TREE_VIEW (view
));
771 view_mode
= VIEW_BOTH
;
772 gtk_tree_selection_set_mode (dccfwin
.sel
, GTK_SELECTION_MULTIPLE
);
774 if (!prefs
.windows_as_tabs
)
775 g_signal_connect (G_OBJECT (dccfwin
.window
), "configure_event",
776 G_CALLBACK (dcc_configure_cb
), 0);
777 g_signal_connect (G_OBJECT (dccfwin
.sel
), "changed",
778 G_CALLBACK (dcc_row_cb
), NULL
);
780 g_signal_connect (G_OBJECT (view
), "row-activated",
781 G_CALLBACK (dcc_dclick_cb
), NULL
);
783 table
= gtk_table_new (1, 3, FALSE
);
784 gtk_table_set_col_spacings (GTK_TABLE (table
), 16);
785 gtk_box_pack_start (GTK_BOX (vbox
), table
, 0, 0, 0);
787 radio
= gtk_radio_button_new_with_mnemonic (NULL
, _("Both"));
788 g_signal_connect (G_OBJECT (radio
), "toggled",
789 G_CALLBACK (dcc_toggle
), GINT_TO_POINTER (VIEW_BOTH
));
790 gtk_table_attach (GTK_TABLE (table
), radio
, 3, 4, 0, 1, GTK_FILL
, GTK_FILL
, 0, 0);
791 group
= gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio
));
793 radio
= gtk_radio_button_new_with_mnemonic (group
, _("Uploads"));
794 g_signal_connect (G_OBJECT (radio
), "toggled",
795 G_CALLBACK (dcc_toggle
), GINT_TO_POINTER (VIEW_UPLOAD
));
796 gtk_table_attach (GTK_TABLE (table
), radio
, 1, 2, 0, 1, GTK_FILL
, GTK_FILL
, 0, 0);
797 group
= gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio
));
799 radio
= gtk_radio_button_new_with_mnemonic (group
, _("Downloads"));
800 g_signal_connect (G_OBJECT (radio
), "toggled",
801 G_CALLBACK (dcc_toggle
), GINT_TO_POINTER (VIEW_DOWNLOAD
));
802 gtk_table_attach (GTK_TABLE (table
), radio
, 2, 3, 0, 1, GTK_FILL
, GTK_FILL
, 0, 0);
804 exp
= gtk_expander_new (_("Details"));
805 gtk_table_attach (GTK_TABLE (table
), exp
, 0, 1, 0, 1, GTK_EXPAND
| GTK_FILL
, GTK_FILL
, 0, 0);
807 detailbox
= gtk_table_new (3, 3, FALSE
);
808 gtk_table_set_col_spacings (GTK_TABLE (detailbox
), 6);
809 gtk_table_set_row_spacings (GTK_TABLE (detailbox
), 2);
810 gtk_container_set_border_width (GTK_CONTAINER (detailbox
), 6);
811 g_signal_connect (G_OBJECT (exp
), "activate",
812 G_CALLBACK (dcc_exp_cb
), detailbox
);
813 gtk_table_attach (GTK_TABLE (table
), detailbox
, 0, 4, 1, 2, GTK_EXPAND
| GTK_FILL
, GTK_FILL
, 0, 0);
815 dccfwin
.file_label
= dcc_detail_label (_("File:"), detailbox
, 0);
816 dccfwin
.address_label
= dcc_detail_label (_("Address:"), detailbox
, 1);
818 bbox
= gtk_hbutton_box_new ();
819 gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox
), GTK_BUTTONBOX_SPREAD
);
820 gtk_box_pack_end (GTK_BOX (vbox
), bbox
, FALSE
, FALSE
, 2);
822 dccfwin
.abort_button
= gtkutil_button (bbox
, GTK_STOCK_CANCEL
, 0, abort_clicked
, 0, _("Abort"));
823 dccfwin
.accept_button
= gtkutil_button (bbox
, GTK_STOCK_APPLY
, 0, accept_clicked
, 0, _("Accept"));
824 dccfwin
.resume_button
= gtkutil_button (bbox
, GTK_STOCK_REFRESH
, 0, resume_clicked
, 0, _("Resume"));
825 dccfwin
.open_button
= gtkutil_button (bbox
, 0, 0, browse_dcc_folder
, 0, _("Open Folder..."));
826 gtk_widget_set_sensitive (dccfwin
.accept_button
, FALSE
);
827 gtk_widget_set_sensitive (dccfwin
.resume_button
, FALSE
);
828 gtk_widget_set_sensitive (dccfwin
.abort_button
, FALSE
);
831 gtk_widget_show_all (dccfwin
.window
);
832 gtk_widget_hide (detailbox
);
838 fe_dcc_open_send_win (int passive
)
840 /* combined send/recv GUI */
841 return fe_dcc_open_recv_win (passive
);
845 /* DCC CHAT GUIs BELOW */
848 dcc_chat_get_selected (void)
850 return treeview_get_selected (GTK_TREE_MODEL (dcccwin
.store
),
851 dcccwin
.sel
, CCOL_DCC
);
855 accept_chat_clicked (GtkWidget
* wid
, gpointer none
)
858 GSList
*start
, *list
;
860 start
= list
= dcc_chat_get_selected ();
861 for (; list
; list
= list
->next
)
866 g_slist_free (start
);
870 abort_chat_clicked (GtkWidget
* wid
, gpointer none
)
873 GSList
*start
, *list
;
875 start
= list
= dcc_chat_get_selected ();
876 for (; list
; list
= list
->next
)
879 dcc_abort (dcc
->serv
->front_session
, dcc
);
881 g_slist_free (start
);
885 dcc_chat_close_cb (void)
887 dcccwin
.window
= NULL
;
891 dcc_chat_append (struct DCC
*dcc
, GtkListStore
*store
, gboolean prepend
)
896 gtk_list_store_prepend (store
, &iter
);
898 gtk_list_store_append (store
, &iter
);
900 dcc_prepare_row_chat (dcc
, store
, &iter
, FALSE
);
904 dcc_chat_fill_win (void)
911 gtk_list_store_clear (GTK_LIST_STORE (dcccwin
.store
));
917 if (dcc
->type
== TYPE_CHATSEND
|| dcc
->type
== TYPE_CHATRECV
)
919 dcc_chat_append (dcc
, dcccwin
.store
, FALSE
);
925 /* if only one entry, select it (so Accept button can work) */
928 gtk_tree_model_get_iter_first (GTK_TREE_MODEL (dcccwin
.store
), &iter
);
929 gtk_tree_selection_select_iter (dcccwin
.sel
, &iter
);
934 dcc_chat_row_cb (GtkTreeSelection
*sel
, gpointer user_data
)
939 list
= dcc_chat_get_selected ();
942 gtk_widget_set_sensitive (dcccwin
.accept_button
, FALSE
);
943 gtk_widget_set_sensitive (dcccwin
.abort_button
, FALSE
);
947 gtk_widget_set_sensitive (dcccwin
.abort_button
, TRUE
);
949 if (list
->next
) /* multi selection */
950 gtk_widget_set_sensitive (dcccwin
.accept_button
, TRUE
);
953 /* turn OFF/ON appropriate buttons */
955 if (dcc
->dccstat
== STAT_QUEUED
&& dcc
->type
== TYPE_CHATRECV
)
956 gtk_widget_set_sensitive (dcccwin
.accept_button
, TRUE
);
958 gtk_widget_set_sensitive (dcccwin
.accept_button
, FALSE
);
965 dcc_chat_dclick_cb (GtkTreeView
*view
, GtkTreePath
*path
,
966 GtkTreeViewColumn
*column
, gpointer data
)
968 accept_chat_clicked (0, 0);
972 fe_dcc_open_chat_win (int passive
)
974 GtkWidget
*view
, *vbox
, *bbox
;
980 mg_bring_tofront (dcccwin
.window
);
985 mg_create_generic_tab ("DCCChat", _("XChat: DCC Chat List"),
986 FALSE
, TRUE
, dcc_chat_close_cb
, NULL
, 550, 180, &vbox
, 0);
987 gtk_container_set_border_width (GTK_CONTAINER (dcccwin
.window
), 3);
988 gtk_box_set_spacing (GTK_BOX (vbox
), 3);
990 store
= gtk_list_store_new (CN_COLUMNS
, G_TYPE_STRING
, G_TYPE_STRING
,
991 G_TYPE_STRING
, G_TYPE_STRING
, G_TYPE_STRING
,
992 G_TYPE_POINTER
, GDK_TYPE_COLOR
);
993 view
= gtkutil_treeview_new (vbox
, GTK_TREE_MODEL (store
), NULL
, -1);
995 dcc_add_column (view
, CCOL_STATUS
, CCOL_COLOR
, _("Status"), FALSE
);
996 dcc_add_column (view
, CCOL_NICK
, CCOL_COLOR
, _("Nick"), FALSE
);
997 dcc_add_column (view
, CCOL_RECV
, CCOL_COLOR
, _("Recv"), TRUE
);
998 dcc_add_column (view
, CCOL_SENT
, CCOL_COLOR
, _("Sent"), TRUE
);
999 dcc_add_column (view
, CCOL_START
, CCOL_COLOR
, _("Start Time"), FALSE
);
1001 gtk_tree_view_column_set_expand (gtk_tree_view_get_column (GTK_TREE_VIEW (view
), 1), TRUE
);
1002 gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (view
), TRUE
);
1004 dcccwin
.list
= view
;
1005 dcccwin
.store
= store
;
1006 dcccwin
.sel
= gtk_tree_view_get_selection (GTK_TREE_VIEW (view
));
1007 gtk_tree_selection_set_mode (dcccwin
.sel
, GTK_SELECTION_MULTIPLE
);
1009 g_signal_connect (G_OBJECT (dcccwin
.sel
), "changed",
1010 G_CALLBACK (dcc_chat_row_cb
), NULL
);
1012 g_signal_connect (G_OBJECT (view
), "row-activated",
1013 G_CALLBACK (dcc_chat_dclick_cb
), NULL
);
1015 bbox
= gtk_hbutton_box_new ();
1016 gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox
), GTK_BUTTONBOX_SPREAD
);
1017 gtk_box_pack_end (GTK_BOX (vbox
), bbox
, FALSE
, FALSE
, 2);
1019 dcccwin
.abort_button
= gtkutil_button (bbox
, GTK_STOCK_CANCEL
, 0, abort_chat_clicked
, 0, _("Abort"));
1020 dcccwin
.accept_button
= gtkutil_button (bbox
, GTK_STOCK_APPLY
, 0, accept_chat_clicked
, 0, _("Accept"));
1021 gtk_widget_set_sensitive (dcccwin
.accept_button
, FALSE
);
1022 gtk_widget_set_sensitive (dcccwin
.abort_button
, FALSE
);
1024 dcc_chat_fill_win ();
1025 gtk_widget_show_all (dcccwin
.window
);
1031 fe_dcc_add (struct DCC
*dcc
)
1036 if (dccfwin
.window
&& (view_mode
& VIEW_DOWNLOAD
))
1037 dcc_append (dcc
, dccfwin
.store
, TRUE
);
1041 if (dccfwin
.window
&& (view_mode
& VIEW_UPLOAD
))
1042 dcc_append (dcc
, dccfwin
.store
, TRUE
);
1047 dcc_chat_append (dcc
, dcccwin
.store
, TRUE
);
1052 fe_dcc_update (struct DCC
*dcc
)
1057 dcc_update_send (dcc
);
1061 dcc_update_recv (dcc
);
1065 dcc_update_chat (dcc
);
1070 fe_dcc_remove (struct DCC
*dcc
)
1080 if (dcc_find_row (dcc
, GTK_TREE_MODEL (dccfwin
.store
), &iter
, COL_DCC
))
1081 gtk_list_store_remove (dccfwin
.store
, &iter
);
1088 if (dcc_find_row (dcc
, GTK_TREE_MODEL (dcccwin
.store
), &iter
, CCOL_DCC
))
1089 gtk_list_store_remove (dcccwin
.store
, &iter
);