source: trunk/gtk/dialogs.c @ 1507

Last change on this file since 1507 was 1507, checked in by joshe, 15 years ago

Calculate and show directory sizes in file window.

  • Property svn:keywords set to Date Rev Author Id
File size: 19.7 KB
Line 
1/******************************************************************************
2 * $Id: dialogs.c 1507 2007-02-23 06:54:49Z joshe $
3 *
4 * Copyright (c) 2005-2007 Transmission authors and contributors
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *****************************************************************************/
24
25#include <errno.h>
26#include <stdlib.h>
27#include <string.h>
28
29#include <gtk/gtk.h>
30#include <glib/gi18n.h>
31
32#include "conf.h"
33#include "dialogs.h"
34#include "tr_icon.h"
35#include "tr_prefs.h"
36#include "util.h"
37
38#include "transmission.h"
39
40#define PREFNAME                "transmission-dialog-pref-name"
41#define FILESWIND_EXTRA_INDENT  4
42
43#define STRIPROOT( path )                                                     \
44    ( g_path_is_absolute( (path) ) ? g_path_skip_root( (path) ) : (path) )
45
46struct addcb {
47  add_torrents_func_t addfunc;
48  void *data;
49  gboolean autostart;
50  gboolean usingaltdir;
51  GtkFileChooser *altdir;
52  GtkButtonBox *altbox;
53};
54
55struct dirdata
56{
57    add_torrents_func_t addfunc;
58    void              * cbdata;
59    GList             * files;
60    guint               flags;
61};
62
63struct quitdata
64{
65    callbackfunc_t func;
66    void         * cbdata;
67};
68
69struct fileswind
70{
71    TrTorrent    * tor;
72    GtkTreeModel * model;
73};
74
75static void
76autoclick(GtkWidget *widget, gpointer gdata);
77static void
78dirclick(GtkWidget *widget, gpointer gdata);
79static void
80addresp(GtkWidget *widget, gint resp, gpointer gdata);
81static void
82promptresp( GtkWidget * widget, gint resp, gpointer data );
83static void
84quitresp( GtkWidget * widget, gint resp, gpointer data );
85static void
86parsepath( GtkTreeStore * store, GtkTreeIter * ret,
87           const char * path, int index, uint64_t size );
88static uint64_t
89getdirtotals( GtkTreeStore * store, GtkTreeIter * parent, tr_file_t * files );
90static void
91setscroll( void * arg );
92static void
93fileswindresp( GtkWidget * widget, gint resp SHUTUP, gpointer data );
94
95void
96makeaddwind(GtkWindow *parent, add_torrents_func_t addfunc, void *cbdata) {
97  GtkWidget *wind = gtk_file_chooser_dialog_new(_("Add a Torrent"), parent,
98    GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
99    GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
100  struct addcb *data = g_new(struct addcb, 1);
101  GtkWidget *vbox = gtk_vbox_new(FALSE, 3);
102  GtkWidget *bbox = gtk_hbutton_box_new();
103  GtkWidget *autocheck = gtk_check_button_new_with_mnemonic(
104    _("Automatically _start torrent"));
105  GtkWidget *dircheck = gtk_check_button_new_with_mnemonic(
106    _("Use alternate _download directory"));
107  GtkFileFilter *filter = gtk_file_filter_new();
108  GtkFileFilter *unfilter = gtk_file_filter_new();
109  GtkWidget *getdir = gtk_file_chooser_button_new(
110    _("Choose a download directory"), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
111
112  data->addfunc = addfunc;
113  data->data = cbdata;
114  data->autostart = TRUE;
115  data->usingaltdir = FALSE;
116  data->altdir = GTK_FILE_CHOOSER(getdir);
117  data->altbox = GTK_BUTTON_BOX(bbox);
118
119  gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_EDGE);
120  gtk_box_pack_start_defaults(GTK_BOX(bbox), dircheck);
121  gtk_box_pack_start_defaults(GTK_BOX(bbox), getdir);
122
123  gtk_box_pack_start_defaults(GTK_BOX(vbox), autocheck);
124  gtk_box_pack_start_defaults(GTK_BOX(vbox), bbox);
125
126  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(autocheck), TRUE);
127  gtk_file_chooser_set_current_folder( GTK_FILE_CHOOSER( getdir ),
128                                       getdownloaddir() );
129
130  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dircheck), FALSE);
131  gtk_widget_set_sensitive(getdir, FALSE);
132
133  gtk_file_filter_set_name(filter, _("Torrent files"));
134  gtk_file_filter_add_pattern(filter, "*.torrent");
135  gtk_file_filter_set_name(unfilter, _("All files"));
136  gtk_file_filter_add_pattern(unfilter, "*");
137
138  gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(wind), filter);
139  gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(wind), unfilter);
140  gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(wind), TRUE);
141  gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(wind), vbox);
142
143  g_signal_connect(G_OBJECT(autocheck), "clicked", G_CALLBACK(autoclick),data);
144  g_signal_connect(G_OBJECT(dircheck), "clicked", G_CALLBACK(dirclick), data);
145  g_signal_connect(G_OBJECT(wind), "response", G_CALLBACK(addresp), data);
146
147  gtk_widget_show_all(wind);
148}
149
150static void
151autoclick(GtkWidget *widget, gpointer gdata) {
152  struct addcb *data = gdata;
153
154  data->autostart = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
155}
156
157static void
158dirclick(GtkWidget *widget, gpointer gdata) {
159  struct addcb *data = gdata;
160
161  data->usingaltdir = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
162  gtk_widget_set_sensitive(GTK_WIDGET(data->altdir), data->usingaltdir);
163}
164
165static void
166addresp(GtkWidget *widget, gint resp, gpointer gdata) {
167  struct addcb *data = gdata;
168  GSList *files, *ii;
169  GList *stupidgtk;
170  int flags;
171  char *dir;
172
173  if(GTK_RESPONSE_ACCEPT == resp) {
174    dir = NULL;
175    if(data->usingaltdir)
176      dir = gtk_file_chooser_get_filename(data->altdir);
177    files = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(widget));
178    stupidgtk = NULL;
179    for(ii = files; NULL != ii; ii = ii->next)
180      stupidgtk = g_list_append(stupidgtk, ii->data);
181    flags = ( data->autostart ? TR_TORNEW_RUNNING : TR_TORNEW_PAUSED );
182    flags |= addactionflag( tr_prefs_get( PREF_ID_ADDSTD ) );
183    data->addfunc( data->data, NULL, stupidgtk, dir, flags );
184    if(NULL != dir)
185      g_free(dir);
186    g_slist_free(files);
187    freestrlist(stupidgtk);
188  }
189
190  g_free( data );
191  gtk_widget_destroy(widget);
192}
193
194#define INFOLINE(tab, ii, nam, val) \
195  do { \
196    char *txt = g_markup_printf_escaped("<b>%s</b>", nam); \
197    GtkWidget *wid = gtk_label_new(NULL); \
198    gtk_misc_set_alignment(GTK_MISC(wid), 0, .5); \
199    gtk_label_set_markup(GTK_LABEL(wid), txt); \
200    gtk_table_attach_defaults(GTK_TABLE(tab), wid, 0, 1, ii, ii + 1); \
201    wid = gtk_label_new(val); \
202    gtk_label_set_selectable(GTK_LABEL(wid), TRUE); \
203    gtk_misc_set_alignment(GTK_MISC(wid), 0, .5); \
204    gtk_table_attach_defaults(GTK_TABLE(tab), wid, 1, 2, ii, ii + 1); \
205    ii++; \
206    g_free(txt); \
207  } while(0)
208
209#define INFOLINEF(tab, ii, fmt, nam, val) \
210  do { \
211    char *buf = g_strdup_printf(fmt, val); \
212    INFOLINE(tab, ii, nam, buf); \
213    g_free(buf); \
214  } while(0)
215
216#define INFOLINEA(tab, ii, nam, val) \
217  do { \
218    char *buf = val; \
219    INFOLINE(tab, ii, nam, buf); \
220    g_free(buf); \
221  } while(0)
222
223#define INFOSEP(tab, ii) \
224  do { \
225    GtkWidget *wid = gtk_hseparator_new(); \
226    gtk_table_attach_defaults(GTK_TABLE(tab), wid, 0, 2, ii, ii + 1); \
227    ii++; \
228  } while(0)
229
230void
231makeinfowind(GtkWindow *parent, TrTorrent *tor) {
232  tr_stat_t *sb;
233  tr_info_t *in;
234  GtkWidget *wind, *label;
235  int ii;
236  char *str;
237  const int rowcount = 15;
238  GtkWidget *table = gtk_table_new(rowcount, 2, FALSE);
239
240  /* XXX should use model and update this window regularly */
241
242  sb = tr_torrent_stat(tor);
243  in = tr_torrent_info(tor);
244  str = g_strdup_printf(_("%s Properties"), in->name);
245  wind = gtk_dialog_new_with_buttons(str, parent,
246    GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
247    GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL);
248  g_free(str);
249
250  gtk_widget_set_name(wind, "TransmissionDialog");
251  gtk_table_set_col_spacings(GTK_TABLE(table), 12);
252  gtk_table_set_row_spacings(GTK_TABLE(table), 12);
253  gtk_dialog_set_default_response(GTK_DIALOG(wind), GTK_RESPONSE_ACCEPT);
254  gtk_container_set_border_width(GTK_CONTAINER(table), 6);
255  gtk_window_set_resizable(GTK_WINDOW(wind), FALSE);
256
257  label = gtk_label_new(NULL);
258  gtk_label_set_selectable(GTK_LABEL(label), TRUE);
259  str = g_markup_printf_escaped("<big>%s</big>", in->name);
260  gtk_label_set_markup(GTK_LABEL(label), str);
261  g_free(str);
262  gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 2, 0, 1);
263
264  ii = 1;
265
266  INFOSEP(table, ii);
267
268  if(80 == sb->trackerPort)
269    INFOLINEA(table, ii, _("Tracker:"), g_strdup_printf("http://%s",
270              sb->trackerAddress));
271  else
272    INFOLINEA(table, ii, _("Tracker:"), g_strdup_printf("http://%s:%i",
273              sb->trackerAddress, sb->trackerPort));
274  INFOLINE(table, ii, _("Announce:"), sb->trackerAnnounce);
275  INFOLINEA(table, ii, _("Piece Size:"), readablesize(in->pieceSize));
276  INFOLINEF(table, ii, "%i", _("Pieces:"), in->pieceCount);
277  INFOLINEA(table, ii, _("Total Size:"), readablesize(in->totalSize));
278  if(0 > sb->seeders)
279    INFOLINE(table, ii, _("Seeders:"), _("?"));
280  else
281    INFOLINEF(table, ii, "%i", _("Seeders:"), sb->seeders);
282  if(0 > sb->leechers)
283    INFOLINE(table, ii, _("Leechers:"), _("?"));
284  else
285    INFOLINEF(table, ii, "%i", _("Leechers:"), sb->leechers);
286  if(0 > sb->completedFromTracker)
287    INFOLINE(table, ii, _("Completed:"), _("?"));
288  else
289    INFOLINEF(table, ii, "%i", _("Completed:"), sb->completedFromTracker);
290
291  INFOSEP(table, ii);
292
293  INFOLINE(table, ii, _("Directory:"), tr_torrentGetFolder(tr_torrent_handle(tor)));
294  INFOLINEA(table, ii, _("Downloaded:"), readablesize(sb->downloaded));
295  INFOLINEA(table, ii, _("Uploaded:"), readablesize(sb->uploaded));
296
297  INFOSEP(table, ii);
298
299  g_assert(rowcount == ii);
300
301  gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(wind)->vbox), table);
302  g_signal_connect(G_OBJECT(wind), "response",
303                   G_CALLBACK(gtk_widget_destroy), NULL);
304  gtk_widget_show_all(wind);
305}
306
307void
308promptfordir( GtkWindow * parent, add_torrents_func_t addfunc, void *cbdata,
309              GList * files, guint flags )
310{
311    struct dirdata * stuff;
312    GtkWidget      * wind;
313
314    stuff = g_new( struct dirdata, 1 );
315    stuff->addfunc = addfunc;
316    stuff->cbdata  = cbdata;
317    stuff->files   = dupstrlist( files );
318    stuff->flags   = flags;
319
320    wind =  gtk_file_chooser_dialog_new( _("Choose a directory"), parent,
321                                         GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
322                                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
323                                         GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
324                                         NULL );
325    gtk_file_chooser_set_local_only( GTK_FILE_CHOOSER( wind ), TRUE );
326    gtk_file_chooser_set_select_multiple( GTK_FILE_CHOOSER( wind ), FALSE );
327    gtk_file_chooser_set_filename( GTK_FILE_CHOOSER( wind ),
328                                   getdownloaddir() );
329
330    g_signal_connect( G_OBJECT( wind ), "response",
331                      G_CALLBACK( promptresp ), stuff );
332
333    gtk_widget_show_all(wind);
334}
335
336static void
337promptresp( GtkWidget * widget, gint resp, gpointer data )
338{
339    struct dirdata * stuff;
340    char           * dir;
341
342    stuff = data;
343
344    if( GTK_RESPONSE_ACCEPT == resp )
345    {
346        dir = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER( widget ) );
347        /* it seems that we will always get a directory */
348        g_assert( NULL != dir );
349        stuff->addfunc( stuff->cbdata, NULL, stuff->files, dir, stuff->flags );
350        g_free( dir );
351    }
352
353    freestrlist( stuff->files );
354    g_free( stuff );
355    gtk_widget_destroy( widget );
356}
357
358void
359askquit( GtkWindow * parent, callbackfunc_t func, void * cbdata )
360{
361    struct quitdata * stuff;
362    GtkWidget * wind;
363
364    stuff          = g_new( struct quitdata, 1 );
365    stuff->func    = func;
366    stuff->cbdata  = cbdata;
367
368    wind = gtk_message_dialog_new( parent, GTK_DIALOG_DESTROY_WITH_PARENT,
369                                   GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
370                                   _("Are you sure you want to quit %s?"),
371                                   g_get_application_name() );
372    gtk_dialog_set_default_response( GTK_DIALOG( wind ), GTK_RESPONSE_YES );
373    g_signal_connect( G_OBJECT( wind ), "response",
374                      G_CALLBACK( quitresp ), stuff );
375
376    gtk_widget_show_all( wind );
377}
378
379static void
380quitresp( GtkWidget * widget, gint resp, gpointer data )
381{
382    struct quitdata * stuff;
383
384    stuff = data;
385
386    if( GTK_RESPONSE_YES == resp )
387    {
388        stuff->func( stuff->cbdata );
389    }
390
391    g_free( stuff );
392    gtk_widget_destroy( widget );
393}
394
395enum filescols { FC_INDEX = 0, FC_LABEL, FC_KEY, FC_STOCK, FC__COUNT };
396
397void
398makefileswind( GtkWindow * parent, TrTorrent * tor )
399{
400    GType cols[] = { G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING };
401    tr_info_t         * inf;
402    GtkTreeStore      * store;
403    int                 ii;
404    GtkWidget         * view, * scroll, * frame, * wind;
405    GtkCellRenderer   * rend;
406    GtkTreeViewColumn * col;
407    GtkTreeSelection  * sel;
408    char              * label;
409    struct fileswind  * fw;
410
411    g_assert( ALEN( cols ) == FC__COUNT );
412
413    /* set up the model */
414    inf   = tr_torrent_info( tor );
415    store = gtk_tree_store_newv( FC__COUNT, cols );
416    for( ii = 0; ii < inf->fileCount; ii++ )
417    {
418        parsepath( store, NULL, STRIPROOT( inf->files[ii].name ),
419                   ii, inf->files[ii].length );
420    }
421    getdirtotals( store, NULL, inf->files );
422    gtk_tree_sortable_set_sort_column_id( GTK_TREE_SORTABLE( store ),
423                                          FC_KEY, GTK_SORT_ASCENDING );
424
425    /* create the view */
426    view = gtk_tree_view_new_with_model( GTK_TREE_MODEL( store ) );
427    col = gtk_tree_view_column_new();
428    gtk_tree_view_column_set_title( col, _("File") );
429    /* add icon renderer */
430    rend = gtk_cell_renderer_pixbuf_new();
431    gtk_tree_view_column_pack_start( col, rend, FALSE );
432    gtk_tree_view_column_add_attribute( col, rend, "stock-id", FC_STOCK );
433    /* add text renderer */
434    rend = gtk_cell_renderer_text_new();
435    gtk_tree_view_column_pack_start( col, rend, TRUE );
436    gtk_tree_view_column_add_attribute( col, rend, "markup", FC_LABEL );
437    gtk_tree_view_append_column( GTK_TREE_VIEW( view ), col );
438    /* set up view */
439    sel = gtk_tree_view_get_selection( GTK_TREE_VIEW( view ) );
440    gtk_tree_selection_set_mode( sel, GTK_SELECTION_NONE );
441    gtk_tree_view_expand_all( GTK_TREE_VIEW( view ) );
442    gtk_tree_view_set_search_column( GTK_TREE_VIEW( view ), FC_LABEL );
443    gtk_widget_show( view );
444
445    /* create the scrolled window and stick the view in it */
446    scroll = gtk_scrolled_window_new( NULL, NULL );
447    gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( scroll ),
448                                    GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC );
449    gtk_container_add( GTK_CONTAINER( scroll ), view );
450    gtk_widget_show( scroll );
451
452    /* create a frame around the scroll to make it look a little better */
453    frame = gtk_frame_new( NULL );
454    gtk_frame_set_shadow_type( GTK_FRAME( frame ), GTK_SHADOW_IN );
455    gtk_container_add( GTK_CONTAINER( frame ), scroll );
456    gtk_widget_show( frame );
457
458    /* create the window */
459    label = g_strdup_printf( _("Files for %s"), inf->name );
460    wind = gtk_dialog_new_with_buttons( label, parent,
461                                        GTK_DIALOG_DESTROY_WITH_PARENT |
462                                        GTK_DIALOG_NO_SEPARATOR, 
463                                        GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
464                                        NULL );
465    g_free( label );
466    gtk_dialog_set_default_response( GTK_DIALOG( wind ), GTK_RESPONSE_ACCEPT );
467    gtk_window_set_resizable( GTK_WINDOW( wind ), TRUE );
468    gtk_box_pack_start_defaults( GTK_BOX( GTK_DIALOG( wind )->vbox ), frame );
469
470    /* set up the callback data */
471    fw        = g_new0( struct fileswind, 1 );
472    fw->tor   = tor;
473    fw->model = GTK_TREE_MODEL( store );
474    g_object_add_weak_pointer( G_OBJECT( tor ), ( gpointer * )&fw->tor );
475    g_signal_connect( wind, "response", G_CALLBACK( fileswindresp ), fw );
476
477    /* show the window with a nice initial size */
478    windowsizehack( wind, scroll, view, setscroll, scroll );
479}
480
481static void
482parsepath( GtkTreeStore * store, GtkTreeIter * ret,
483           const char * path, int index, uint64_t size )
484{
485    GtkTreeModel * model;
486    GtkTreeIter  * parent, start, iter;
487    char         * file, * dir, * mykey, * modelkey, * label, * sizestr;
488    const char   * stock;
489
490    model  = GTK_TREE_MODEL( store );
491    parent = NULL;
492    file   = g_path_get_basename( path );
493    if( 0 != strcmp( file, path ) )
494    {
495        dir = g_path_get_dirname( path );
496        parsepath( store, &start, dir, index, size );
497        g_free( dir );
498        parent = &start;
499    }
500
501    mykey = g_utf8_collate_key( file, -1 );
502    if( gtk_tree_model_iter_children( model, &iter, parent ) )
503    {
504        do
505        {
506            gtk_tree_model_get( model, &iter, FC_KEY, &modelkey, -1 );
507            if( NULL != modelkey && 0 == strcmp( mykey, modelkey ) )
508            {
509                goto done;
510            }
511        }
512        while( gtk_tree_model_iter_next( model, &iter ) );
513    }
514
515    gtk_tree_store_append( store, &iter, parent );
516    if( NULL == ret )
517    {
518        sizestr = readablesize( size );
519        label = g_markup_printf_escaped( _("<small>%s (%s)</small>"),
520                                         file, sizestr );
521        g_free( file );
522        file = label;
523        g_free( sizestr );
524        stock = GTK_STOCK_FILE;
525    }
526    else
527    {
528        stock = GTK_STOCK_DIRECTORY;
529        index = -1;
530    }
531    gtk_tree_store_set( store, &iter, FC_INDEX, index, FC_LABEL, file,
532                        FC_KEY, mykey, FC_STOCK, stock, -1 );
533  done:
534    g_free( mykey );
535    g_free( file );
536    if( NULL != ret )
537    {
538        memcpy( ret, &iter, sizeof( iter ) );
539    }
540}
541
542static uint64_t
543getdirtotals( GtkTreeStore * store, GtkTreeIter * parent, tr_file_t * files )
544{
545    GtkTreeModel * model;
546    GtkTreeIter    iter;
547    int            index;
548    uint64_t       mysize, subsize;
549    char         * sizestr, * name, * label;
550
551    model  = GTK_TREE_MODEL( store );
552    mysize = 0;
553    if( gtk_tree_model_iter_children( model, &iter, parent ) )
554    {
555        do
556        {
557            if( gtk_tree_model_iter_has_child( model, &iter ) )
558            {
559                subsize = getdirtotals( store, &iter, files );
560                mysize += subsize;
561                gtk_tree_model_get( model, &iter, FC_LABEL, &name, -1 );
562                sizestr = readablesize( subsize );
563                label = g_markup_printf_escaped( _("<small>%s (%s)</small>"),
564                                                 name, sizestr );
565                g_free( sizestr );
566                g_free( name );
567                gtk_tree_store_set( store, &iter, FC_LABEL, label, -1 );
568                g_free( label );
569            }
570            else
571            {
572                gtk_tree_model_get( model, &iter, FC_INDEX, &index, -1 );
573                g_assert( 0 <= index );
574                mysize += files[index].length;
575            }
576        }
577        while( gtk_tree_model_iter_next( model, &iter ) );
578    }
579
580    return mysize;
581}
582
583static void
584setscroll( void * arg )
585{
586    gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( arg ),
587        GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
588}
589
590static void
591fileswindresp( GtkWidget * widget, gint resp SHUTUP, gpointer data )
592{
593    struct fileswind * fw;
594
595    fw = data;
596
597    g_object_unref( fw->model );
598    g_object_remove_weak_pointer( G_OBJECT( fw->tor ),
599                                  ( gpointer * )&fw->tor );
600    g_free( fw );
601    gtk_widget_destroy( widget );
602}
Note: See TracBrowser for help on using the repository browser.