1 | /****************************************************************************** |
---|
2 | * $Id: file-list.c 5290 2008-03-18 19:14:21Z charles $ |
---|
3 | * |
---|
4 | * Copyright (c) 2005-2008 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 <stddef.h> |
---|
26 | #include <stdio.h> |
---|
27 | #include <stdlib.h> |
---|
28 | #include <glib/gi18n.h> |
---|
29 | #include <gtk/gtk.h> |
---|
30 | |
---|
31 | #include <libtransmission/transmission.h> |
---|
32 | |
---|
33 | #include "file-list.h" |
---|
34 | #include "hig.h" |
---|
35 | |
---|
36 | enum |
---|
37 | { |
---|
38 | FC_STOCK, |
---|
39 | FC_LABEL, |
---|
40 | FC_PROG, |
---|
41 | FC_KEY, |
---|
42 | FC_INDEX, |
---|
43 | FC_SIZE, |
---|
44 | FC_PRIORITY, |
---|
45 | FC_ENABLED, |
---|
46 | N_FILE_COLS |
---|
47 | }; |
---|
48 | |
---|
49 | typedef struct |
---|
50 | { |
---|
51 | TrTorrent * gtor; |
---|
52 | GtkWidget * top; |
---|
53 | GtkWidget * view; |
---|
54 | GtkTreeModel * model; /* same object as store, but recast */ |
---|
55 | GtkTreeStore * store; /* same object as model, but recast */ |
---|
56 | guint timeout_tag; |
---|
57 | } |
---|
58 | FileData; |
---|
59 | |
---|
60 | static const char* |
---|
61 | priorityToString( const int priority ) |
---|
62 | { |
---|
63 | switch( priority ) { |
---|
64 | /* this refers to priority */ |
---|
65 | case TR_PRI_HIGH: return _("High"); |
---|
66 | /* this refers to priority */ |
---|
67 | case TR_PRI_NORMAL: return _("Normal"); |
---|
68 | /* this refers to priority */ |
---|
69 | case TR_PRI_LOW: return _("Low"); |
---|
70 | default: return "BUG!"; |
---|
71 | } |
---|
72 | } |
---|
73 | |
---|
74 | static tr_priority_t |
---|
75 | stringToPriority( const char* str ) |
---|
76 | { |
---|
77 | if( !strcmp( str, priorityToString( TR_PRI_HIGH ) ) ) return TR_PRI_HIGH; |
---|
78 | if( !strcmp( str, priorityToString( TR_PRI_LOW ) ) ) return TR_PRI_LOW; |
---|
79 | return TR_PRI_NORMAL; |
---|
80 | } |
---|
81 | |
---|
82 | static void |
---|
83 | parsepath( const tr_torrent * tor, |
---|
84 | GtkTreeStore * store, |
---|
85 | GtkTreeIter * ret, |
---|
86 | const char * path, |
---|
87 | int index, |
---|
88 | uint64_t size ) |
---|
89 | { |
---|
90 | GtkTreeModel * model; |
---|
91 | GtkTreeIter * parent, start, iter; |
---|
92 | char * file, * lower, * mykey, *escaped=0; |
---|
93 | const char * stock; |
---|
94 | int priority = 0; |
---|
95 | gboolean enabled = TRUE; |
---|
96 | |
---|
97 | model = GTK_TREE_MODEL( store ); |
---|
98 | parent = NULL; |
---|
99 | file = g_path_get_basename( path ); |
---|
100 | if( 0 != strcmp( file, path ) ) |
---|
101 | { |
---|
102 | char * dir = g_path_get_dirname( path ); |
---|
103 | parsepath( tor, store, &start, dir, index, size ); |
---|
104 | parent = &start; |
---|
105 | g_free( dir ); |
---|
106 | } |
---|
107 | |
---|
108 | lower = g_utf8_casefold( file, -1 ); |
---|
109 | mykey = g_utf8_collate_key( lower, -1 ); |
---|
110 | if( gtk_tree_model_iter_children( model, &iter, parent ) ) do |
---|
111 | { |
---|
112 | gboolean stop; |
---|
113 | char * modelkey; |
---|
114 | gtk_tree_model_get( model, &iter, FC_KEY, &modelkey, -1 ); |
---|
115 | stop = (modelkey!=NULL) && !strcmp(mykey,modelkey); |
---|
116 | g_free (modelkey); |
---|
117 | if (stop) goto done; |
---|
118 | } |
---|
119 | while( gtk_tree_model_iter_next( model, &iter ) ); |
---|
120 | |
---|
121 | gtk_tree_store_append( store, &iter, parent ); |
---|
122 | if( NULL == ret ) |
---|
123 | { |
---|
124 | stock = GTK_STOCK_FILE; |
---|
125 | } |
---|
126 | else |
---|
127 | { |
---|
128 | stock = GTK_STOCK_DIRECTORY; |
---|
129 | size = 0; |
---|
130 | index = -1; |
---|
131 | } |
---|
132 | |
---|
133 | if (index != -1) { |
---|
134 | priority = tr_torrentGetFilePriority( tor, index ); |
---|
135 | enabled = tr_torrentGetFileDL( tor, index ); |
---|
136 | } |
---|
137 | |
---|
138 | escaped = g_markup_escape_text (file, -1); |
---|
139 | gtk_tree_store_set( store, &iter, FC_INDEX, index, |
---|
140 | FC_LABEL, escaped, |
---|
141 | FC_KEY, mykey, |
---|
142 | FC_STOCK, stock, |
---|
143 | FC_PRIORITY, priorityToString(priority), |
---|
144 | FC_ENABLED, enabled, |
---|
145 | FC_SIZE, size, -1 ); |
---|
146 | done: |
---|
147 | g_free( escaped ); |
---|
148 | g_free( mykey ); |
---|
149 | g_free( lower ); |
---|
150 | g_free( file ); |
---|
151 | if( NULL != ret ) |
---|
152 | *ret = iter; |
---|
153 | } |
---|
154 | |
---|
155 | static uint64_t |
---|
156 | getdirtotals( GtkTreeStore * store, GtkTreeIter * parent ) |
---|
157 | { |
---|
158 | GtkTreeModel * model; |
---|
159 | GtkTreeIter iter; |
---|
160 | uint64_t mysize, subsize; |
---|
161 | char * name, * label; |
---|
162 | |
---|
163 | model = GTK_TREE_MODEL( store ); |
---|
164 | mysize = 0; |
---|
165 | if( gtk_tree_model_iter_children( model, &iter, parent ) ) do |
---|
166 | { |
---|
167 | char sizeStr[64]; |
---|
168 | if( gtk_tree_model_iter_has_child( model, &iter ) ) |
---|
169 | { |
---|
170 | subsize = getdirtotals( store, &iter ); |
---|
171 | gtk_tree_store_set( store, &iter, FC_SIZE, subsize, -1 ); |
---|
172 | } |
---|
173 | else |
---|
174 | { |
---|
175 | gtk_tree_model_get( model, &iter, FC_SIZE, &subsize, -1 ); |
---|
176 | } |
---|
177 | gtk_tree_model_get( model, &iter, FC_LABEL, &name, -1 ); |
---|
178 | tr_strlsize( sizeStr, subsize, sizeof( sizeStr ) ); |
---|
179 | label = g_markup_printf_escaped( "<small>%s (%s)</small>", |
---|
180 | name, sizeStr ); |
---|
181 | g_free( name ); |
---|
182 | gtk_tree_store_set( store, &iter, FC_LABEL, label, -1 ); |
---|
183 | g_free( label ); |
---|
184 | mysize += subsize; |
---|
185 | } |
---|
186 | while( gtk_tree_model_iter_next( model, &iter ) ); |
---|
187 | |
---|
188 | return mysize; |
---|
189 | } |
---|
190 | |
---|
191 | static void |
---|
192 | updateprogress( GtkTreeModel * model, |
---|
193 | GtkTreeStore * store, |
---|
194 | GtkTreeIter * parent, |
---|
195 | tr_file_stat * fileStats, |
---|
196 | guint64 * setmeGotSize, |
---|
197 | guint64 * setmeTotalSize) |
---|
198 | { |
---|
199 | GtkTreeIter iter; |
---|
200 | guint64 gotSize=0, totalSize=0; |
---|
201 | |
---|
202 | if( gtk_tree_model_iter_children( model, &iter, parent ) ) do |
---|
203 | { |
---|
204 | int oldProg, newProg; |
---|
205 | guint64 subGot, subTotal; |
---|
206 | |
---|
207 | if (gtk_tree_model_iter_has_child( model, &iter ) ) |
---|
208 | { |
---|
209 | updateprogress( model, store, &iter, fileStats, &subGot, &subTotal); |
---|
210 | } |
---|
211 | else |
---|
212 | { |
---|
213 | int index, percent; |
---|
214 | gtk_tree_model_get( model, &iter, FC_SIZE, &subTotal, |
---|
215 | FC_INDEX, &index, |
---|
216 | -1 ); |
---|
217 | g_assert( 0 <= index ); |
---|
218 | percent = (int)(fileStats[index].progress * 100.0); /* [0...100] */ |
---|
219 | subGot = (guint64)(subTotal * percent/100.0); |
---|
220 | } |
---|
221 | |
---|
222 | if (!subTotal) subTotal = 1; /* avoid div by zero */ |
---|
223 | g_assert (subGot <= subTotal); |
---|
224 | |
---|
225 | /* why not just set it every time? |
---|
226 | because that causes the "priorities" combobox to pop down */ |
---|
227 | gtk_tree_model_get (model, &iter, FC_PROG, &oldProg, -1); |
---|
228 | newProg = (int)(100.0*subGot/subTotal); |
---|
229 | if (oldProg != newProg) |
---|
230 | gtk_tree_store_set (store, &iter, |
---|
231 | FC_PROG, (int)(100.0*subGot/subTotal), -1); |
---|
232 | |
---|
233 | gotSize += subGot; |
---|
234 | totalSize += subTotal; |
---|
235 | } |
---|
236 | while( gtk_tree_model_iter_next( model, &iter ) ); |
---|
237 | |
---|
238 | *setmeGotSize = gotSize; |
---|
239 | *setmeTotalSize = totalSize; |
---|
240 | } |
---|
241 | |
---|
242 | static GtkTreeModel* |
---|
243 | priority_model_new (void) |
---|
244 | { |
---|
245 | GtkTreeIter iter; |
---|
246 | GtkListStore * store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT); |
---|
247 | gtk_list_store_append (store, &iter); |
---|
248 | gtk_list_store_set (store, &iter, 0, priorityToString( TR_PRI_HIGH ), 1, TR_PRI_HIGH, -1); |
---|
249 | gtk_list_store_append (store, &iter); |
---|
250 | gtk_list_store_set (store, &iter, 0, priorityToString( TR_PRI_NORMAL ), 1, TR_PRI_NORMAL, -1); |
---|
251 | gtk_list_store_append (store, &iter); |
---|
252 | gtk_list_store_set (store, &iter, 0, priorityToString( TR_PRI_LOW ), 1, TR_PRI_LOW, -1); |
---|
253 | return GTK_TREE_MODEL (store); |
---|
254 | } |
---|
255 | |
---|
256 | static void |
---|
257 | subtree_walk_dnd( GtkTreeStore * store, |
---|
258 | GtkTreeIter * iter, |
---|
259 | tr_torrent * tor, |
---|
260 | gboolean enabled, |
---|
261 | GArray * indices ) |
---|
262 | { |
---|
263 | int index; |
---|
264 | GtkTreeIter child; |
---|
265 | |
---|
266 | /* update this node */ |
---|
267 | gtk_tree_model_get( GTK_TREE_MODEL(store), iter, FC_INDEX, &index, -1 ); |
---|
268 | if (index >= 0) |
---|
269 | g_array_append_val( indices, index ); |
---|
270 | gtk_tree_store_set( store, iter, FC_ENABLED, enabled, -1 ); |
---|
271 | |
---|
272 | /* visit the children */ |
---|
273 | if( gtk_tree_model_iter_children( GTK_TREE_MODEL(store), &child, iter ) ) do |
---|
274 | subtree_walk_dnd( store, &child, tor, enabled, indices ); |
---|
275 | while( gtk_tree_model_iter_next( GTK_TREE_MODEL(store), &child ) ); |
---|
276 | } |
---|
277 | |
---|
278 | static void |
---|
279 | set_subtree_dnd( GtkTreeStore * store, |
---|
280 | GtkTreeIter * iter, |
---|
281 | tr_torrent * tor, |
---|
282 | gboolean enabled ) |
---|
283 | { |
---|
284 | GArray * indices = g_array_new( FALSE, FALSE, sizeof(int) ); |
---|
285 | subtree_walk_dnd( store, iter, tor, enabled, indices ); |
---|
286 | tr_torrentSetFileDLs( tor, (int*)indices->data, (int)indices->len, enabled ); |
---|
287 | g_array_free( indices, TRUE ); |
---|
288 | } |
---|
289 | |
---|
290 | static void |
---|
291 | subtree_walk_priority( GtkTreeStore * store, |
---|
292 | GtkTreeIter * iter, |
---|
293 | tr_torrent * tor, |
---|
294 | int priority, |
---|
295 | GArray * indices ) |
---|
296 | { |
---|
297 | int index; |
---|
298 | GtkTreeIter child; |
---|
299 | |
---|
300 | /* update this node */ |
---|
301 | gtk_tree_model_get( GTK_TREE_MODEL(store), iter, FC_INDEX, &index, -1 ); |
---|
302 | if( index >= 0 ) |
---|
303 | g_array_append_val( indices, index ); |
---|
304 | gtk_tree_store_set( store, iter, FC_PRIORITY, priorityToString(priority), -1 ); |
---|
305 | |
---|
306 | /* visit the children */ |
---|
307 | if( gtk_tree_model_iter_children( GTK_TREE_MODEL(store), &child, iter ) ) do |
---|
308 | subtree_walk_priority( store, &child, tor, priority, indices ); |
---|
309 | while( gtk_tree_model_iter_next( GTK_TREE_MODEL(store), &child ) ); |
---|
310 | |
---|
311 | } |
---|
312 | |
---|
313 | static void |
---|
314 | set_subtree_priority( GtkTreeStore * store, |
---|
315 | GtkTreeIter * iter, |
---|
316 | tr_torrent * tor, |
---|
317 | int priority ) |
---|
318 | { |
---|
319 | GArray * indices = g_array_new( FALSE, FALSE, sizeof(int) ); |
---|
320 | subtree_walk_priority( store, iter, tor, priority, indices ); |
---|
321 | tr_torrentSetFilePriorities( tor, (int*)indices->data, (int)indices->len, priority ); |
---|
322 | g_array_free( indices, TRUE ); |
---|
323 | } |
---|
324 | |
---|
325 | static void |
---|
326 | priority_changed_cb (GtkCellRendererText * cell UNUSED, |
---|
327 | const gchar * path, |
---|
328 | const gchar * value, |
---|
329 | void * file_data) |
---|
330 | { |
---|
331 | GtkTreeIter iter; |
---|
332 | FileData * d = file_data; |
---|
333 | if (gtk_tree_model_get_iter_from_string (d->model, &iter, path)) |
---|
334 | { |
---|
335 | tr_torrent * tor = tr_torrent_handle( d->gtor ); |
---|
336 | const tr_priority_t priority = stringToPriority( value ); |
---|
337 | set_subtree_priority( d->store, &iter, tor, priority ); |
---|
338 | } |
---|
339 | } |
---|
340 | |
---|
341 | static void |
---|
342 | enabled_toggled (GtkCellRendererToggle * cell UNUSED, |
---|
343 | const gchar * path_str, |
---|
344 | gpointer data_gpointer) |
---|
345 | { |
---|
346 | FileData * data = data_gpointer; |
---|
347 | GtkTreePath * path = gtk_tree_path_new_from_string( path_str ); |
---|
348 | GtkTreeModel * model = data->model; |
---|
349 | GtkTreeIter iter; |
---|
350 | gboolean enabled; |
---|
351 | |
---|
352 | gtk_tree_model_get_iter( model, &iter, path ); |
---|
353 | gtk_tree_model_get( model, &iter, FC_ENABLED, &enabled, -1 ); |
---|
354 | enabled = !enabled; |
---|
355 | set_subtree_dnd( GTK_TREE_STORE(model), |
---|
356 | &iter, |
---|
357 | tr_torrent_handle( data->gtor ), |
---|
358 | enabled ); |
---|
359 | |
---|
360 | gtk_tree_path_free( path ); |
---|
361 | } |
---|
362 | |
---|
363 | static gboolean |
---|
364 | refreshModel( gpointer gdata ) |
---|
365 | { |
---|
366 | FileData * data = gdata; |
---|
367 | |
---|
368 | g_assert( data != NULL ); |
---|
369 | |
---|
370 | if( data->gtor ) |
---|
371 | { |
---|
372 | guint64 foo, bar; |
---|
373 | int fileCount; |
---|
374 | tr_torrent * tor; |
---|
375 | tr_file_stat * fileStats; |
---|
376 | |
---|
377 | tor = tr_torrent_handle( data->gtor ); |
---|
378 | fileCount = 0; |
---|
379 | fileStats = tr_torrentFiles( tor, &fileCount ); |
---|
380 | updateprogress (data->model, data->store, NULL, fileStats, &foo, &bar); |
---|
381 | tr_torrentFilesFree( fileStats, fileCount ); |
---|
382 | } |
---|
383 | |
---|
384 | return TRUE; |
---|
385 | } |
---|
386 | |
---|
387 | static void |
---|
388 | clearData( FileData * data ) |
---|
389 | { |
---|
390 | data->gtor = NULL; |
---|
391 | |
---|
392 | if( data->timeout_tag ) { |
---|
393 | g_source_remove( data->timeout_tag ); |
---|
394 | data->timeout_tag = 0; |
---|
395 | } |
---|
396 | } |
---|
397 | |
---|
398 | void |
---|
399 | file_list_set_torrent( GtkWidget * w, TrTorrent * gtor ) |
---|
400 | { |
---|
401 | GtkTreeStore * store; |
---|
402 | FileData * data; |
---|
403 | |
---|
404 | data = g_object_get_data( G_OBJECT( w ), "file-data" ); |
---|
405 | |
---|
406 | /* unset the old fields */ |
---|
407 | clearData( data ); |
---|
408 | |
---|
409 | /* instantiate the model */ |
---|
410 | store = gtk_tree_store_new ( N_FILE_COLS, |
---|
411 | G_TYPE_STRING, /* stock */ |
---|
412 | G_TYPE_STRING, /* label */ |
---|
413 | G_TYPE_INT, /* prog [0..100] */ |
---|
414 | G_TYPE_STRING, /* key */ |
---|
415 | G_TYPE_INT, /* index */ |
---|
416 | G_TYPE_UINT64, /* size */ |
---|
417 | G_TYPE_STRING, /* priority */ |
---|
418 | G_TYPE_BOOLEAN ); /* dl enabled */ |
---|
419 | data->store = store; |
---|
420 | data->model = GTK_TREE_MODEL( store ); |
---|
421 | data->gtor = gtor; |
---|
422 | |
---|
423 | |
---|
424 | /* populate the model */ |
---|
425 | if( gtor ) |
---|
426 | { |
---|
427 | int i; |
---|
428 | const tr_info * inf = tr_torrent_info( gtor ); |
---|
429 | tr_torrent * tor = tr_torrent_handle( gtor ); |
---|
430 | |
---|
431 | for( i=0; inf && i<inf->fileCount; ++i ) |
---|
432 | { |
---|
433 | const char * path = inf->files[i].name; |
---|
434 | const char * base = g_path_is_absolute( path ) ? g_path_skip_root( path ) : path; |
---|
435 | parsepath( tor, store, NULL, base, i, inf->files[i].length ); |
---|
436 | } |
---|
437 | |
---|
438 | getdirtotals( store, NULL ); |
---|
439 | |
---|
440 | data->timeout_tag = g_timeout_add( 1000, refreshModel, data ); |
---|
441 | } |
---|
442 | |
---|
443 | gtk_tree_view_set_model( GTK_TREE_VIEW( data->view ), GTK_TREE_MODEL( store ) ); |
---|
444 | gtk_tree_view_expand_all( GTK_TREE_VIEW( data->view ) ); |
---|
445 | } |
---|
446 | |
---|
447 | static void |
---|
448 | freeData( gpointer gdata ) |
---|
449 | { |
---|
450 | FileData * data = gdata; |
---|
451 | clearData( data ); |
---|
452 | g_free( data ); |
---|
453 | } |
---|
454 | |
---|
455 | GtkWidget * |
---|
456 | file_list_new( TrTorrent * gtor ) |
---|
457 | { |
---|
458 | GtkWidget * ret; |
---|
459 | FileData * data; |
---|
460 | GtkWidget * view, * scroll; |
---|
461 | GtkCellRenderer * rend; |
---|
462 | GtkCellRenderer * priority_rend; |
---|
463 | GtkCellRenderer * enabled_rend; |
---|
464 | GtkTreeViewColumn * col; |
---|
465 | GtkTreeSelection * sel; |
---|
466 | GtkTreeModel * model; |
---|
467 | |
---|
468 | /* create the view */ |
---|
469 | view = gtk_tree_view_new( ); |
---|
470 | gtk_container_set_border_width( GTK_CONTAINER( view ), GUI_PAD_BIG ); |
---|
471 | |
---|
472 | /* add file column */ |
---|
473 | |
---|
474 | col = GTK_TREE_VIEW_COLUMN (g_object_new (GTK_TYPE_TREE_VIEW_COLUMN, |
---|
475 | "expand", TRUE, |
---|
476 | /* Translators: this is a column header in Files tab, Details dialog; |
---|
477 | Don't include the prefix "filedetails|" in the translation. */ |
---|
478 | "title", Q_("filedetails|File"), |
---|
479 | NULL)); |
---|
480 | rend = gtk_cell_renderer_pixbuf_new(); |
---|
481 | gtk_tree_view_column_pack_start( col, rend, FALSE ); |
---|
482 | gtk_tree_view_column_add_attribute( col, rend, "stock-id", FC_STOCK ); |
---|
483 | /* add text renderer */ |
---|
484 | rend = gtk_cell_renderer_text_new(); |
---|
485 | g_object_set( rend, "ellipsize", PANGO_ELLIPSIZE_END, NULL ); |
---|
486 | gtk_tree_view_column_pack_start( col, rend, TRUE ); |
---|
487 | gtk_tree_view_column_add_attribute( col, rend, "markup", FC_LABEL ); |
---|
488 | gtk_tree_view_append_column( GTK_TREE_VIEW( view ), col ); |
---|
489 | /* add progress column */ |
---|
490 | rend = gtk_cell_renderer_progress_new(); |
---|
491 | /* Translators: this is a column header in Files tab, Details dialog; |
---|
492 | Don't include the prefix "filedetails|" in the translation. */ |
---|
493 | col = gtk_tree_view_column_new_with_attributes (Q_("filedetails|Progress"), |
---|
494 | rend, |
---|
495 | "value", FC_PROG, |
---|
496 | NULL); |
---|
497 | gtk_tree_view_column_set_sort_column_id( col, FC_PROG ); |
---|
498 | gtk_tree_view_append_column( GTK_TREE_VIEW( view ), col ); |
---|
499 | /* set up view */ |
---|
500 | sel = gtk_tree_view_get_selection( GTK_TREE_VIEW( view ) ); |
---|
501 | gtk_tree_view_expand_all( GTK_TREE_VIEW( view ) ); |
---|
502 | gtk_tree_view_set_search_column( GTK_TREE_VIEW( view ), FC_LABEL ); |
---|
503 | |
---|
504 | /* add "download" checkbox column */ |
---|
505 | col = gtk_tree_view_column_new (); |
---|
506 | gtk_tree_view_column_set_sort_column_id( col, FC_ENABLED ); |
---|
507 | rend = enabled_rend = gtk_cell_renderer_toggle_new (); |
---|
508 | /* Translators: this is a column header in Files tab, Details dialog; |
---|
509 | Don't include the prefix "filedetails|" in the translation. |
---|
510 | Please note the items for this column are checkboxes (yes/no) */ |
---|
511 | col = gtk_tree_view_column_new_with_attributes (Q_("filedetails|Download"), |
---|
512 | rend, |
---|
513 | "active", FC_ENABLED, |
---|
514 | NULL); |
---|
515 | gtk_tree_view_append_column( GTK_TREE_VIEW( view ), col ); |
---|
516 | |
---|
517 | /* add priority column */ |
---|
518 | model = priority_model_new (); |
---|
519 | col = gtk_tree_view_column_new (); |
---|
520 | gtk_tree_view_column_set_sort_column_id( col, FC_PRIORITY ); |
---|
521 | /* Translators: this is a column header in Files tab, Details dialog; |
---|
522 | Don't include the prefix "filedetails|" in the translation. */ |
---|
523 | gtk_tree_view_column_set_title (col, Q_("filedetails|Priority")); |
---|
524 | rend = priority_rend = gtk_cell_renderer_combo_new (); |
---|
525 | gtk_tree_view_column_pack_start (col, rend, TRUE); |
---|
526 | g_object_set (G_OBJECT(rend), "model", model, |
---|
527 | "editable", TRUE, |
---|
528 | "has-entry", FALSE, |
---|
529 | "text-column", 0, |
---|
530 | NULL); |
---|
531 | g_object_unref (G_OBJECT(model)); |
---|
532 | gtk_tree_view_column_add_attribute (col, rend, "text", FC_PRIORITY); |
---|
533 | gtk_tree_view_append_column( GTK_TREE_VIEW( view ), col ); |
---|
534 | |
---|
535 | /* create the scrolled window and stick the view in it */ |
---|
536 | scroll = gtk_scrolled_window_new( NULL, NULL ); |
---|
537 | gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( scroll ), |
---|
538 | GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC ); |
---|
539 | gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(scroll), |
---|
540 | GTK_SHADOW_IN); |
---|
541 | gtk_container_add( GTK_CONTAINER( scroll ), view ); |
---|
542 | gtk_widget_set_size_request (scroll, 0u, 200u); |
---|
543 | |
---|
544 | ret = scroll; |
---|
545 | data = g_new0( FileData, 1 ); |
---|
546 | data->view = view; |
---|
547 | data->top = scroll; |
---|
548 | g_signal_connect (G_OBJECT(priority_rend), "edited", G_CALLBACK(priority_changed_cb), data); |
---|
549 | g_signal_connect(enabled_rend, "toggled", G_CALLBACK(enabled_toggled), data ); |
---|
550 | g_object_set_data_full( G_OBJECT( ret ), "file-data", data, freeData ); |
---|
551 | file_list_set_torrent( ret, gtor ); |
---|
552 | |
---|
553 | return ret; |
---|
554 | } |
---|