Changeset 3375 for trunk/jons-gtk2-gui

Show
Ignore:
Timestamp:
03/17/03 03:41:36 (6 years ago)
Author:
bostjanlah
Message:

Make file transfer both ways work again

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • trunk/jons-gtk2-gui/src/file_window.cpp

    r3324 r3375  
    2222#include "licq_gtk.h" 
    2323#include "licq_log.h" 
     24#include "utilities.h" 
     25 
     26using namespace std; 
    2427 
    2528GSList *fs_list; 
     
    3841    GtkWidget *total_files; 
    3942    GtkWidget *local_file_name; 
    40     GtkWidget *batch; 
    4143    GtkWidget *batch_progress; 
    42     GtkWidget *batch_size; 
    43     GtkWidget *progress; 
    44     GtkWidget *file_size; 
     44    GtkWidget *file_progress; 
    4545    GtkWidget *time; 
    46     GtkWidget *bps; 
    4746    GtkWidget *eta; 
    4847    GtkWidget *status; 
     
    7069    GtkWidget *send_urgent;     // Send it urgently 
    7170    GtkWidget *send_list;       // Send it to their list 
    72     GtkWidget *file_select;     // File selection widget 
    7371 
    7472    /* Internals */ 
     
    7775}; 
    7876 
    79 void save_file(struct file_accept *fa); 
    8077void create_file_window(struct file_window *fw); 
    81 void update_file_info(struct file_window *fw); 
    8278struct file_send *fs_find(gulong uin); 
    83 void accept_file(GtkWidget *, gpointer); 
    84 void refuse_file(GtkWidget *, gpointer); 
    85 void refusal_ok(GtkWidget *, gpointer); 
    86 void cancel_file(GtkWidget *, gpointer); 
     79void accept_file(GtkWidget *, struct file_accept *fa); 
     80void refuse_file(GtkWidget *, struct file_accept *fa); 
     81void cancel_file(GtkWidget *, struct file_window *fw); 
    8782void file_pipe_callback(gpointer, gint, GdkInputCondition); 
    88 gchar *encode_file_size(unsigned long); 
    89 void fs_browse_click(GtkWidget *, gpointer); 
    90 void fs_ok_click(GtkWidget *, gpointer); 
    91 void fs_cancel_click(GtkWidget *, gpointer); 
    92 void file_select_ok(GtkWidget *, gpointer); 
    93 void file_select_cancel(GtkWidget *, gpointer); 
    94 void file_start_send(ICQEvent *); 
    95  
    96 void file_accept_window(ICQUser *user, CUserEvent *e, bool auto_accept) 
    97 { 
    98     struct file_accept *fa = (struct file_accept *)g_new0(struct file_accept, 1); 
     83 
     84gboolean 
     85fa_delete(GtkWidget *, GdkEvent *, gpointer data) 
     86{ 
     87    g_free(data); 
     88    return FALSE; 
     89} 
     90 
     91void  
     92file_accept_window(ICQUser *user, CUserEvent *e, bool auto_accept) 
     93{ 
     94    struct file_accept *fa = g_new0(struct file_accept, 1); 
    9995    fa->user = user; 
    10096    fa->e = e; 
    10197 
    102     if(auto_accept) 
    103     { 
    104         accept_file(0, (gpointer)fa); 
     98    if (auto_accept) { 
     99        accept_file(0, fa); 
    105100        return; 
    106101    } 
    107  
    108     GtkWidget *accept; 
    109     GtkWidget *refuse; 
    110     GtkWidget *v_box; 
    111     GtkWidget *h_box; 
    112     GtkWidget *label; 
    113     const gchar *title = g_strdup_printf("File From %s", user->GetAlias()); 
    114102 
    115103    // Make the window 
    116104    fa->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 
     105    char *title = g_strdup_printf("File From %s", user->GetAlias()); 
    117106    gtk_window_set_title(GTK_WINDOW(fa->window), title); 
     107    g_free(title); 
    118108    gtk_window_set_position(GTK_WINDOW(fa->window), GTK_WIN_POS_CENTER); 
    119109 
    120110    // Make the boxes 
    121     v_box = gtk_vbox_new(FALSE, 5); 
    122     h_box = gtk_hbox_new(FALSE, 5); 
    123  
    124     // The label 
    125     const gchar *text = g_strdup_printf("File: %s (%ld bytes)", 
    126                         ((CEventFile *)e)->Filename(), 
    127                         ((CEventFile *)e)->FileSize()); 
    128     label = gtk_label_new(text); 
    129  
    130     // Pack the label 
    131     gtk_box_pack_start(GTK_BOX(v_box), label, FALSE, FALSE, 10); 
     111    GtkWidget *v_box = gtk_vbox_new(FALSE, 5); 
     112 
     113    // Description 
     114    GtkWidget *tv = gtk_text_view_new(); 
     115    gtk_text_view_set_editable(GTK_TEXT_VIEW(tv), FALSE); 
     116    gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(tv), GTK_WRAP_WORD); 
     117    gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(tv), FALSE); 
     118    GtkTextBuffer *tb = gtk_text_view_get_buffer(GTK_TEXT_VIEW(tv)); 
     119    gtk_text_buffer_set_text(tb, e->Text(), -1); 
     120    gtk_widget_set_size_request(tv, 300, -1); 
     121     
     122    GtkWidget *frame = gtk_frame_new(0); 
     123    gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);  
     124    gtk_container_add(GTK_CONTAINER(frame), tv); 
     125    gtk_box_pack_start(GTK_BOX(v_box), frame, FALSE, FALSE, 5); 
    132126 
    133127    // The buttons 
    134     accept = gtk_button_new_with_mnemonic("_Accept"); 
    135     refuse = gtk_button_new_with_mnemonic("_Refuse"); 
     128    GtkWidget *accept = gtk_button_new_with_mnemonic("_Accept"); 
     129    GtkWidget *refuse = gtk_button_new_with_mnemonic("_Refuse"); 
    136130 
    137131    // Pack them 
    138     gtk_box_pack_start(GTK_BOX(h_box), accept, TRUE, TRUE, 0); 
    139     gtk_box_pack_start(GTK_BOX(h_box), refuse, TRUE, TRUE, 0); 
    140     gtk_box_pack_start(GTK_BOX(v_box), h_box, FALSE, FALSE, 10); 
    141  
     132    GtkWidget *h_box = gtk_hbutton_box_new(); 
     133    gtk_button_box_set_layout(GTK_BUTTON_BOX(h_box), GTK_BUTTONBOX_END); 
     134    gtk_box_set_spacing(GTK_BOX(h_box), 5); 
     135    gtk_container_add(GTK_CONTAINER(h_box), accept); 
     136    gtk_container_add(GTK_CONTAINER(h_box), refuse); 
     137 
     138    gtk_box_pack_start(GTK_BOX(v_box), h_box, FALSE, FALSE, 0); 
     139    gtk_container_add(GTK_CONTAINER(fa->window), v_box); 
     140     
    142141    // Connect the signals 
    143     g_signal_connect(G_OBJECT(fa->window), "destroy", 
    144                G_CALLBACK(window_close), fa->window); 
     142    g_signal_connect(G_OBJECT(fa->window), "delete_event", 
     143               G_CALLBACK(fa_delete), fa); 
    145144    g_signal_connect(G_OBJECT(refuse), "clicked", 
    146                G_CALLBACK(refuse_file), (gpointer)fa); 
     145               G_CALLBACK(refuse_file), fa); 
    147146    g_signal_connect(G_OBJECT(accept), "clicked", 
    148                G_CALLBACK(accept_file), (gpointer)fa); 
    149  
    150     gtk_container_add(GTK_CONTAINER(fa->window), v_box); 
     147               G_CALLBACK(accept_file), fa); 
     148 
     149    gtk_container_set_border_width(GTK_CONTAINER(fa->window), 10); 
    151150    gtk_widget_show_all(fa->window); 
    152151} 
    153152 
    154 void refuse_file(GtkWidget *widget, gpointer _fa) 
    155 { 
    156     struct file_accept *fa = (struct file_accept *)_fa; 
    157  
    158     // Close the unnecessary open window 
     153void 
     154refusal_ok(GtkWidget *widget, struct file_accept *fa) 
     155{ 
     156    CEventFile *f = (CEventFile *)fa->e; 
     157 
     158    string reason(textview_get_chars(fa->text)); 
     159    if (reason.empty()) // user gave no reason 
     160        reason = "No reason given."; 
     161 
     162    icq_daemon->icqFileTransferRefuse(fa->user->Uin(), 
     163        reason.c_str(), fa->e->Sequence(),  
     164        f->MessageID(), 
     165        f->IsDirect()); 
     166 
     167    // once refused close all windows 
     168    window_close(0, fa->window2); 
    159169    window_close(0, fa->window); 
    160  
     170    g_free(fa); 
     171} 
     172 
     173void 
     174refuse_file(GtkWidget *widget, struct file_accept *fa) 
     175{ 
    161176    // Create a window to get a reason for not accepting it 
    162      
    163     // The window 
    164177    fa->window2 = gtk_window_new(GTK_WINDOW_TOPLEVEL); 
    165     gtk_window_set_title(GTK_WINDOW(fa->window2), "File Refusal"); 
     178    gtk_window_set_title(GTK_WINDOW(fa->window2), "Refuse File Request"); 
    166179     
    167180    // The box for the items in the window 
     
    172185    fa->text = gtk_text_view_new(); 
    173186    gtk_text_view_set_editable(GTK_TEXT_VIEW(fa->text), TRUE); 
    174     gtk_box_pack_start(GTK_BOX(v_box), fa->text, FALSE, FALSE, 0); 
    175  
    176     // The ok button 
     187    gtk_widget_set_size_request(fa->text, 300, 50); 
     188 
     189    GtkWidget *frame = gtk_frame_new("Reason:"); 
     190    gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);  
     191    gtk_container_add(GTK_CONTAINER(frame), fa->text); 
     192    gtk_box_pack_start(GTK_BOX(v_box), frame, FALSE, FALSE, 0); 
     193 
     194    // Buttons 
     195    GtkWidget *h_box = gtk_hbutton_box_new(); 
     196    gtk_button_box_set_layout(GTK_BUTTON_BOX(h_box), GTK_BUTTONBOX_END); 
    177197    GtkWidget *ok = gtk_button_new_from_stock(GTK_STOCK_OK); 
    178     gtk_box_pack_start(GTK_BOX(v_box), ok, FALSE, FALSE, 0); 
     198    GtkWidget *cancel = gtk_button_new_from_stock(GTK_STOCK_CANCEL); 
     199    gtk_box_pack_start(GTK_BOX(h_box), ok, FALSE, FALSE, 0); 
     200    gtk_box_pack_start(GTK_BOX(h_box), cancel, FALSE, FALSE, 0); 
     201    gtk_box_pack_start(GTK_BOX(v_box), h_box, FALSE, FALSE, 0); 
    179202 
    180203    // Connect all the signals 
    181204    g_signal_connect(G_OBJECT(ok), "clicked", 
    182                G_CALLBACK(refusal_ok), (gpointer)fa); 
    183     g_signal_connect(G_OBJECT(fa->window2), "destroy", 
    184                G_CALLBACK(refusal_ok), (gpointer)fa); 
    185      
     205               G_CALLBACK(refusal_ok), fa); 
     206    g_signal_connect(G_OBJECT(cancel), "clicked", 
     207               G_CALLBACK(window_close), fa->window2); 
     208     
     209    gtk_container_set_border_width(GTK_CONTAINER(fa->window2), 10); 
    186210    gtk_widget_show_all(fa->window2); 
    187211} 
    188212 
    189 void refusal_ok(GtkWidget *widget, gpointer _fa) 
    190 { 
    191     struct file_accept *fa = (struct file_accept *)_fa; 
    192     const char *reason = gtk_editable_get_chars(GTK_EDITABLE(fa->text), 
    193                 0, -1); 
    194     CEventFile *f = (CEventFile *)fa->e; 
    195      
    196  
    197     // The user gave a reason 
    198     if((strcmp(reason, "") != 0)) 
    199     { 
    200         icq_daemon->icqFileTransferRefuse(fa->user->Uin(), 
    201             reason, fa->e->Sequence(),  
    202             f->MessageID(), 
    203             f->IsDirect()); 
    204     } 
    205      
    206     // Use a default reason 
    207     else 
    208     { 
    209         icq_daemon->icqFileTransferRefuse(fa->user->Uin(), 
    210             "No reason given.", fa->e->Sequence(), 
    211             f->MessageID(), 
    212             f->IsDirect() 
    213             ); 
    214     } 
    215  
    216     window_close(0, fa->window2); 
    217 } 
    218  
    219 void accept_file(GtkWidget *widget, gpointer _fa) 
    220 { 
    221     struct file_accept *fa = (struct file_accept *)_fa; 
    222  
    223     // Close the unnecessary open window 
    224     if(fa->window) 
    225         window_close(0, fa->window); 
    226  
    227     save_file(fa); 
    228 } 
    229  
    230 void save_file(struct file_accept *fa) 
     213void 
     214save_file(struct file_accept *fa, char *filename) 
    231215{ 
    232216    struct file_window *fw; 
     
    245229 
    246230    // Get the HOME environment variable 
    247     const char *home = getenv("HOME"); 
    248     fw->ftman->ReceiveFiles(home); 
     231    char *p = strrchr(filename, '/'); 
     232    if (p != NULL) 
     233        *p = '\0'; 
     234     
     235    fw->ftman->ReceiveFiles(filename); 
    249236 
    250237    fw->input_tag = gtk_input_add_full(fw->ftman->Pipe(), GDK_INPUT_READ, 
    251                       file_pipe_callback, NULL, (gpointer)fw, NULL); 
     238            file_pipe_callback, NULL, fw, NULL); 
    252239 
    253240    // Actually accept the file 
    254241    icq_daemon->icqFileTransferAccept(fw->uin, 
    255                       fw->ftman->LocalPort(), 
    256                       fw->sequence, 
    257                       f->MessageID(), 
    258                       f->IsDirect()); 
    259 } 
    260  
    261 void create_file_window(struct file_window *fw) 
    262 { 
    263     GtkWidget *table; 
    264     GtkWidget *label; 
    265     GtkWidget *h_box; 
    266  
    267     // The box for the entry widgets 
    268     h_box = gtk_hbox_new(FALSE, 5); 
    269  
     242            fw->ftman->LocalPort(), 
     243            fw->sequence, 
     244            f->MessageID(), 
     245            f->IsDirect()); 
     246} 
     247 
     248void 
     249accept_file(GtkWidget *widget, struct file_accept *fa) 
     250{ 
     251    GtkWidget *file_selector =  
     252            gtk_file_selection_new("Please select destination directory"); 
     253    char *dest_dir = g_strdup_printf("%s/", getenv("HOME")); 
     254    gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_selector), dest_dir); 
     255    int response = gtk_dialog_run(GTK_DIALOG(file_selector)); 
     256    if (response == GTK_RESPONSE_OK) { 
     257        char *file_name = g_strdup( 
     258                gtk_file_selection_get_filename(GTK_FILE_SELECTION(file_selector))); 
     259        gtk_widget_destroy(GTK_WIDGET(file_selector)); 
     260        if (fa->window) 
     261            window_close(0, fa->window); 
     262        save_file(fa, file_name); 
     263        g_free(fa); 
     264    } 
     265    else 
     266        gtk_widget_destroy(GTK_WIDGET(file_selector)); 
     267} 
     268 
     269GtkWidget * 
     270ro_entry_new(int width_chars, const char *sample = NULL) 
     271{ 
     272    GtkWidget *entry = gtk_entry_new(); 
     273    //gtk_widget_set_size_request(fw->current_file_name, 200, 20); 
     274    if (sample == NULL) 
     275        gtk_entry_set_width_chars(GTK_ENTRY(entry), width_chars); 
     276    else { 
     277        PangoLayout *layout = gtk_entry_get_layout(GTK_ENTRY(entry)); 
     278        pango_layout_set_text(layout, sample, -1); 
     279        int wd, ht; 
     280        pango_layout_get_pixel_size(layout, &wd, &ht); 
     281        gtk_widget_set_size_request(entry, wd + 20, -1); 
     282        pango_layout_set_text(layout, "", -1); 
     283    } 
     284    gtk_entry_set_editable(GTK_ENTRY(entry), FALSE); 
     285    gtk_widget_set_sensitive(entry, FALSE); 
     286     
     287    return entry; 
     288} 
     289 
     290void 
     291create_file_window(struct file_window *fw) 
     292{ 
    270293    // The window 
    271294    fw->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 
    272     gtk_window_set_title(GTK_WINDOW(fw->window), 
    273                  g_strdup_printf("Licq - File Transfer (%ld)", 
    274                              fw->uin)); 
     295    char *title = g_strdup_printf("Licq - File Transfer (%ld)", fw->uin); 
     296    gtk_window_set_title(GTK_WINDOW(fw->window), title); 
     297    g_free(title); 
    275298 
    276299    // Create the table and add it to the window 
    277     table = gtk_table_new(7, 2, FALSE); 
     300    GtkWidget *table = gtk_table_new(7, 2, FALSE); 
    278301    gtk_container_add(GTK_CONTAINER(fw->window), table); 
    279302 
    280303    // Current file label 
    281     label = gtk_label_new("Current File:"); 
    282     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, 
    283              GTK_FILL, GTK_FILL, 3, 3); 
     304    gtk_table_attach(GTK_TABLE(table), 
     305            gtk_label_new("Current File:"),  
     306            0, 1, 0, 1, 
     307            GTK_FILL, GTK_FILL, 3, 3); 
    284308 
    285309    // Current file entry box 
    286     fw->current_file_name = gtk_entry_new(); 
    287     gtk_widget_set_size_request(fw->current_file_name, 200, 20); 
    288     gtk_box_pack_start(GTK_BOX(h_box), fw->current_file_name, FALSE, 
    289                FALSE, 0); 
     310    fw->current_file_name = ro_entry_new(50); 
     311    gtk_table_attach(GTK_TABLE(table), 
     312            fw->current_file_name,  
     313            1, 2, 0, 1, 
     314            GTK_FILL, GTK_FILL, 3, 3); 
    290315 
    291316    // Total number of files entry box 
    292     fw->total_files = gtk_entry_new(); 
    293     gtk_widget_set_size_request(fw->total_files, 50, 20); 
    294     gtk_box_pack_start(GTK_BOX(h_box), fw->total_files, FALSE, FALSE, 0); 
    295  
    296     // Attach the box with the current file namd and total files 
    297     // to this table.  This will be the format for all of the entry 
    298     // boxes to follow in this window. 
    299     gtk_table_attach(GTK_TABLE(table), h_box, 1, 2, 0, 1, 
    300              GtkAttachOptions(GTK_FILL | GTK_EXPAND), 
    301              GtkAttachOptions(GTK_FILL | GTK_EXPAND), 
    302              3, 3); 
     317    fw->total_files = ro_entry_new(0, "99 / 99"); 
     318    gtk_table_attach(GTK_TABLE(table), 
     319            fw->total_files,  
     320            2, 3, 0, 1, 
     321            GTK_FILL, GTK_FILL, 3, 3); 
    303322 
    304323    // Local file name label 
    305     label = gtk_label_new("File Name:"); 
    306     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, 
    307              GTK_FILL, GTK_FILL, 3, 3); 
    308  
    309     // New box 
    310     h_box = gtk_hbox_new(FALSE, 5); 
    311      
     324    gtk_table_attach(GTK_TABLE(table), gtk_label_new("File Name:"),  
     325            0, 1, 1, 2, 
     326            GTK_FILL, GTK_FILL, 3, 3); 
     327 
    312328    // Local file name entry box 
    313     fw->local_file_name = gtk_entry_new(); 
    314     gtk_widget_set_size_request(fw->local_file_name, 255, 20); 
    315     gtk_box_pack_start(GTK_BOX(h_box), fw->local_file_name, FALSE, 
    316                FALSE, 0); 
     329    fw->local_file_name = ro_entry_new(50); 
    317330 
    318331    // Attach it 
    319     gtk_table_attach(GTK_TABLE(table), h_box, 1, 2, 1, 2, 
    320              GtkAttachOptions(GTK_FILL | GTK_EXPAND), 
    321              GtkAttachOptions(GTK_FILL | GTK_EXPAND), 
    322              3, 3); 
     332    gtk_table_attach(GTK_TABLE(table),  
     333            fw->local_file_name, 
     334            1, 3, 1, 2, 
     335            GtkAttachOptions(GTK_FILL | GTK_EXPAND), 
     336            GtkAttachOptions(GTK_FILL | GTK_EXPAND), 
     337            3, 3); 
    323338                
    324339    // Current file label 
    325     label = gtk_label_new("File:"); 
    326     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3, 
    327              GTK_FILL, GTK_FILL, 3, 3); 
    328  
    329     // New box 
    330     h_box = gtk_hbox_new(FALSE, 5); 
     340    gtk_table_attach(GTK_TABLE(table), gtk_label_new("File:"),  
     341            0, 1, 2, 3, 
     342            GTK_FILL, GTK_FILL, 3, 3); 
    331343 
    332344    // Progress bar for current file 
    333     fw->progress = gtk_progress_bar_new(); 
    334     gtk_progress_bar_set_text(GTK_PROGRESS_BAR(fw->progress), "%p%%"); 
    335     //gtk_progress_set_text_alignment(GTK_PROGRESS_BAR(fw->progress), 0.5, 0.5); 
    336     //gtk_progress_set_format_string(GTK_PROGRESS_BAR(fw->progress), "%p%%"); 
    337     gtk_widget_set_size_request(fw->progress, 160, 20); 
    338     gtk_box_pack_start(GTK_BOX(h_box), fw->progress, FALSE, FALSE, 0); 
    339  
    340     // Current file size 
    341     fw->file_size = gtk_entry_new(); 
    342     gtk_widget_set_size_request(fw->file_size, 90, 20); 
    343     gtk_box_pack_start(GTK_BOX(h_box), fw->file_size, FALSE, FALSE, 0); 
    344  
    345     // Attach it 
    346     gtk_table_attach(GTK_TABLE(table), h_box, 1, 2, 2, 3, 
    347              GtkAttachOptions(GTK_FILL | GTK_EXPAND), 
    348              GtkAttachOptions(GTK_FILL | GTK_EXPAND), 
    349              3, 3); 
     345    fw->file_progress = gtk_progress_bar_new(); 
     346    gtk_table_attach(GTK_TABLE(table),  
     347            fw->file_progress, 
     348            1, 3, 2, 3, 
     349            GTK_FILL, GTK_FILL, 3, 3); 
    350350 
    351351    // Batch label 
    352     label = gtk_label_new("Batch:"); 
    353     gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4, 
    354              GTK_FILL, GTK_FILL, 3, 3); 
    355  
    356     // New box 
    357     h_box = gtk_hbox_new(FALSE, 5); 
    358      
     352    gtk_table_attach(GTK_TABLE(table),  
     353            gtk_label_new("Batch:"),  
     354            0, 1, 3, 4, 
     355            GTK_FILL, GTK_FILL, 3, 3); 
     356 
    359357    // Batch progress bar 
    360358    fw->batch_progress = gtk_progress_bar_new(); 
    361     gtk_progress_bar_set_text(GTK_PROGRESS_BAR(fw->batch_progress), "%p%%"); 
    362     gtk_widget_set_size_request(fw->batch_progress, 160, 20); 
    363     gtk_box_pack_start(GTK_BOX(h_box), fw->batch_progress, FALSE, 
    364                FALSE, 0); 
    365359 
    366360    // Batch size entry box 
    367     fw->batch_size = gtk_entry_new(); 
    368     gtk_widget_set_size_request(fw->batch_size, 90, 20); 
    369     gtk_box_pack_start(GTK_BOX(h_box), fw->batch_size, FALSE, FALSE, 0); 
    370  
    371     // Attach it 
    372     gtk_table_attach(GTK_TABLE(table), h_box, 1, 2, 3, 4, 
    373              GtkAttachOptions(GTK_FILL | GTK_EXPAND), 
    374              GtkAttachOptions(GTK_FILL | GTK_EXPAND), 
    375              3, 3); 
     361    gtk_table_attach(GTK_TABLE(table),  
     362            fw->batch_progress, 
     363            1, 3, 3, 4, 
     364            GTK_FILL, GTK_FILL, 3, 3); 
    376365 
    377366    // This box will contain the time (how long it's been receiving), 
    378367    // ETA, and BPS 
    379     h_box = gtk_hbox_new(FALSE, 5); 
     368    GtkWidget *h_box = gtk_hbox_new(FALSE, 5); 
    380369     
    381370    // The time label and entry box 
    382     label = gtk_label_new("Time:"); 
    383     fw->time = gtk_entry_new(); 
    384     gtk_widget_set_size_request(fw->time, 65, 20); 
    385     gtk_widget_set_sensitive(fw->time, FALSE); 
    386  
    387     // Pack them 
    388     gtk_box_pack_start(GTK_BOX(h_box), label, FALSE, FALSE, 5); 
     371    gtk_box_pack_start(GTK_BOX(h_box), gtk_label_new("Time:"), FALSE, FALSE, 5); 
     372    fw->time = ro_entry_new(0, "00:00:00"); 
    389373    gtk_box_pack_start(GTK_BOX(h_box), fw->time, FALSE, FALSE, 0); 
    390374 
    391375    // The ETA label and entry box 
    392     label = gtk_label_new("ETA:"); 
    393     fw->eta = gtk_entry_new(); 
    394     gtk_widget_set_size_request(fw->eta, 65, 20); 
    395     gtk_widget_set_sensitive(fw->eta, FALSE); 
    396  
    397     // Pack them 
    398     gtk_box_pack_start(GTK_BOX(h_box), label, FALSE, FALSE, 5); 
     376    gtk_box_pack_start(GTK_BOX(h_box), gtk_label_new("ETA:"), FALSE, FALSE, 5); 
     377    fw->eta = ro_entry_new(0, "00:00:00"); 
    399378    gtk_box_pack_start(GTK_BOX(h_box), fw->eta, FALSE, FALSE, 0); 
    400379     
    401380    // The BPS label and entry box 
    402     label = gtk_label_new("BPS:"); 
    403     fw->bps = gtk_entry_new(); 
    404     gtk_widget_set_size_request(fw->bps, 65, 20); 
    405     gtk_widget_set_sensitive(fw->bps, FALSE); 
    406  
    407     // Pack them 
    408     gtk_box_pack_start(GTK_BOX(h_box), label, FALSE, FALSE, 5); 
    409     gtk_box_pack_start(GTK_BOX(h_box), fw->bps, FALSE, FALSE, 0); 
    410  
     381    //gtk_box_pack_start(GTK_BOX(h_box), gtk_label_new("BPS:"), FALSE, FALSE, 5); 
     382    //fw->bps = ro_entry_new(0, "000.0 Bytes/s"); 
     383    //gtk_box_pack_start(GTK_BOX(h_box), fw->bps, FALSE, FALSE, 0); 
    411384 
    412385    // Add the box to the table 
    413     gtk_table_attach(GTK_TABLE(table), h_box, 0, 2, 4, 5, 
    414              GtkAttachOptions(GTK_FILL | GTK_EXPAND), 
    415              GtkAttachOptions(GTK_FILL | GTK_EXPAND), 
    416              3, 3); 
     386    gtk_table_attach(GTK_TABLE(table),  
     387            h_box,  
     388            1, 3, 4, 5, 
     389            GtkAttachOptions(GTK_FILL | GTK_EXPAND), 
     390            GtkAttachOptions(GTK_FILL | GTK_EXPAND), 
     391            3, 3); 
    417392 
    418393    // Cancel button 
    419     fw->cancel = gtk_button_new_from_stock(GTK_STOCK_CANCEL); 
    420     gtk_table_attach(GTK_TABLE(table), fw->cancel, 1, 2, 5, 6, 
    421              GtkAttachOptions(GTK_FILL | GTK_EXPAND), 
    422              GtkAttachOptions(GTK_FILL | GTK_EXPAND), 
    423              3, 3); 
     394  fw->cancel = gtk_button_new_from_stock(GTK_STOCK_CANCEL); 
     395  GtkWidget *bbox = gtk_hbutton_box_new(); 
     396    gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END); 
     397  gtk_container_add(GTK_CONTAINER(bbox), fw->cancel); 
     398   
     399    GtkWidget *hbox = gtk_hbox_new(FALSE, 5); 
     400    fw->status = gtk_statusbar_new(); 
     401    gtk_box_pack_start(GTK_BOX(hbox), fw->status, TRUE, TRUE, 0); 
     402    gtk_box_pack_end(GTK_BOX(hbox), bbox, FALSE, FALSE, 0); 
     403     
     404    gtk_table_attach(GTK_TABLE(table),  
     405            hbox,  
     406            0, 3, 5, 6, 
     407            GtkAttachOptions(GTK_FILL | GTK_EXPAND), 
     408            GtkAttachOptions(GTK_FILL | GTK_EXPAND), 
     409            3, 3); 
     410 
    424411    g_signal_connect(G_OBJECT(fw->cancel), "clicked", 
    425               G_CALLBACK(cancel_file), (gpointer)fw); 
     412              G_CALLBACK(cancel_file), fw); 
    426413     
    427414    gtk_widget_show_all(fw->window); 
    428415} 
    429416 
    430 void cancel_file(GtkWidget *widget, gpointer _fw) 
    431 { 
    432     struct file_window *fw = (struct file_window *)_fw; 
    433  
     417void  
     418cancel_file(GtkWidget *widget, struct file_window *fw) 
     419{ 
    434420    const gchar *label_text = gtk_button_get_label(GTK_BUTTON(fw->cancel)); 
    435421 
    436     if(strcasecmp(label_text, "Cancel") == 0) 
    437     { 
     422    if (strcasecmp(label_text, "Cancel") == 0) 
    438423        // Cancel the transfer 
    439424        fw->ftman->CloseFileTransfer(); 
    440     } 
    441425 
    442426    gtk_input_remove(fw->input_tag); 
     
    446430} 
    447431 
    448 void file_pipe_callback(gpointer data, gint pipe, GdkInputCondition cond) 
     432string 
     433to_str_free(char *p) 
     434{ 
     435    string s(p); 
     436    g_free(p); 
     437    return s; 
     438} 
     439 
     440std::string 
     441encode_file_size(unsigned long size) 
     442{ 
     443    gchar unit[6]; 
     444     
     445    if (size >= (1024 * 1024)) { 
     446        size /= (1024*1024) / 10; 
     447        strcpy(unit, "MB"); 
     448    } 
     449    else if (size >= 1024) { 
     450        size /= (1024 / 10); 
     451        strcpy(unit, "KB"); 
     452    } 
     453    else if (size != 1) { 
     454        size *= 10; 
     455        strcpy(unit, "Bytes"); 
     456    } 
     457    else { 
     458        size *= 10; 
     459        strcpy(unit, "Byte"); 
     460    } 
     461 
     462    return  
     463        to_str_free(g_strdup_printf("%ld.%ld %s", (size / 10), (size % 10), unit)); 
     464} 
     465 
     466void  
     467update_file_info(struct file_window *fw) 
     468{ 
     469    // Time 
     470    time_t elapsed = time(0) - fw->ftman->StartTime(); 
     471 
     472    if (fw->ftman->FileSize() == 0 || fw->ftman->BatchSize() == 0) 
     473        return; 
     474 
     475    char *txt; 
     476    if (elapsed != 0) { 
     477        g_strdup_printf("%02ld:%02ld:%02ld", 
     478                elapsed / 3600, (elapsed % 3600) / 60, (elapsed % 60)); 
     479        gtk_entry_set_text(GTK_ENTRY(fw->time), txt); 
     480        g_free(txt); 
     481    } 
     482     
     483    // File progress 
     484    if (elapsed != 0) 
     485        txt = g_strdup_printf("%s/%s, %s/s", 
     486                encode_file_size(fw->ftman->FilePos()).c_str(), 
     487                encode_file_size(fw->ftman->FileSize()).c_str(), 
     488                encode_file_size(fw->ftman->BytesTransfered() / elapsed).c_str()); 
     489    else 
     490        txt = g_strdup_printf("%s/%s", 
     491                encode_file_size(fw->ftman->FilePos()).c_str(), 
     492                encode_file_size(fw->ftman->FileSize()).c_str()); 
     493    gtk_progress_bar_set_text(GTK_PROGRESS_BAR(fw->file_progress), txt); 
     494    g_free(txt); 
     495 
     496    // Update progress percent 
     497    gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(fw->file_progress),  
     498            ((gfloat)fw->ftman->FilePos() / fw->ftman->FileSize())); 
     499 
     500    // Batch progress 
     501    if (elapsed != 0) 
     502        txt = g_strdup_printf("%s/%s, %s/s", 
     503                encode_file_size(fw->ftman->BatchPos()).c_str(), 
     504                encode_file_size(fw->ftman->BatchSize()).c_str(), 
     505                encode_file_size(fw->ftman->BatchPos() / elapsed).c_str()); 
     506    else 
     507        txt = g_strdup_printf("%s/%s", 
     508                encode_file_size(fw->ftman->BatchPos()).c_str(), 
     509                encode_file_size(fw->ftman->BatchSize()).c_str()); 
     510    gtk_progress_bar_set_text(GTK_PROGRESS_BAR(fw->batch_progress), txt);