source: trunk/gtk/torrent-cell-renderer.c @ 7982

Last change on this file since 7982 was 7982, checked in by charles, 13 years ago

(trunk gtk) #1824: Display ETA when seeding

  • Property svn:keywords set to Date Rev Author Id
File size: 25.0 KB
Line 
1/*
2 * This file Copyright (C) 2007-2009 Charles Kerr <charles@transmissionbt.com>
3 *
4 * This file is licensed by the GPL version 2.  Works owned by the
5 * Transmission project are granted a special exemption to clause 2(b)
6 * so that the bulk of its code can remain under the MIT license.
7 * This exemption does not extend to derived works not owned by
8 * the Transmission project.
9 *
10 * $Id: torrent-cell-renderer.c 7982 2009-03-01 16:00:41Z charles $
11 */
12
13#include "assert.h"
14#include <gtk/gtk.h>
15#include <glib/gi18n.h>
16#include <libtransmission/transmission.h>
17#include "hig.h"
18#include "torrent-cell-renderer.h"
19#include "tr-torrent.h"
20#include "util.h"
21
22/* #define TEST_RTL */
23
24enum
25{
26    P_TORRENT = 1,
27    P_BAR_HEIGHT,
28    P_MINIMAL
29};
30
31#define DEFAULT_BAR_HEIGHT 12
32
33/***
34****
35***/
36
37static char*
38getProgressString( const tr_torrent * tor,
39                   const tr_info    * info,
40                   const tr_stat    * torStat )
41{
42    const int      isDone = torStat->leftUntilDone == 0;
43    const uint64_t haveTotal = torStat->haveUnchecked + torStat->haveValid;
44    const int      isSeed = torStat->haveValid >= info->totalSize;
45    char           buf1[32], buf2[32], buf3[32], buf4[32];
46    char *         str;
47    double         seedRatio; 
48    gboolean       hasSeedRatio;
49
50    if( !isDone )
51    {
52        str = g_strdup_printf(
53            /* %1$s is how much we've got,
54               %2$s is how much we'll have when done,
55               %3$.2f%% is a percentage of the two */
56            _( "%1$s of %2$s (%3$.2f%%)" ),
57            tr_strlsize( buf1, haveTotal, sizeof( buf1 ) ),
58            tr_strlsize( buf2, torStat->sizeWhenDone, sizeof( buf2 ) ),
59            torStat->percentDone * 100.0 );
60    }
61    else if( !isSeed )
62    {
63        str = g_strdup_printf(
64            /* %1$s is how much we've got,
65               %2$s is the torrent's total size,
66               %3$.2f%% is a percentage of the two,
67               %4$s is how much we've uploaded,
68               %5$s is our upload-to-download ratio */
69            _( "%1$s of %2$s (%3$.2f%%), uploaded %4$s (Ratio: %5$s)" ),
70            tr_strlsize( buf1, haveTotal, sizeof( buf1 ) ),
71            tr_strlsize( buf2, info->totalSize, sizeof( buf2 ) ),
72            torStat->percentComplete * 100.0,
73            tr_strlsize( buf3, torStat->uploadedEver, sizeof( buf3 ) ),
74            tr_strlratio( buf4, torStat->ratio, sizeof( buf4 ) ) );
75    }
76    else if(( hasSeedRatio = tr_torrentGetSeedRatio( tor, &seedRatio )))
77    {
78        str = g_strdup_printf(
79            /* %1$s is the torrent's total size,
80               %2$s is how much we've uploaded,
81               %3$s is our upload-to-download ratio,
82               $4$s is the ratio we want to reach before we stop uploading */
83            _( "%1$s, uploaded %2$s (Ratio: %3$s Goal: %4$s)" ),
84            tr_strlsize( buf1, info->totalSize, sizeof( buf1 ) ),
85            tr_strlsize( buf2, torStat->uploadedEver, sizeof( buf2 ) ),
86            tr_strlratio( buf3, torStat->ratio, sizeof( buf3 ) ),
87            tr_strlratio( buf4, seedRatio, sizeof( buf4 ) ) );
88    }
89    else /* seeding w/o a ratio */
90    {
91        str = g_strdup_printf(
92            /* %1$s is the torrent's total size,
93               %2$s is how much we've uploaded,
94               %3$s is our upload-to-download ratio */
95            _( "%1$s, uploaded %2$s (Ratio: %3$s)" ),
96            tr_strlsize( buf1, info->totalSize, sizeof( buf1 ) ),
97            tr_strlsize( buf2, torStat->uploadedEver, sizeof( buf2 ) ),
98            tr_strlratio( buf3, torStat->ratio, sizeof( buf3 ) ) );
99    }
100
101    /* add time when downloading */
102    if( hasSeedRatio || ( torStat->activity == TR_STATUS_DOWNLOAD ) )
103    {
104        const int eta = torStat->eta;
105        GString * gstr = g_string_new( str );
106        g_string_append( gstr, " - " );
107        if( eta < 0 )
108            g_string_append( gstr, _( "Remaining time unknown" ) );
109        else
110        {
111            char timestr[128];
112            tr_strltime( timestr, eta, sizeof( timestr ) );
113            /* time remaining */
114            g_string_append_printf( gstr, _( "%s remaining" ), timestr );
115        }
116        g_free( str );
117        str = g_string_free( gstr, FALSE );
118    }
119
120    return str;
121}
122
123static char*
124getShortTransferString( const tr_stat * torStat,
125                        char *          buf,
126                        size_t          buflen )
127{
128    char      downStr[32], upStr[32];
129    const int haveDown = torStat->peersSendingToUs > 0;
130    const int haveUp = torStat->peersGettingFromUs > 0;
131
132    if( haveDown )
133        tr_strlspeed( downStr, torStat->pieceDownloadSpeed, sizeof( downStr ) );
134    if( haveUp )
135        tr_strlspeed( upStr, torStat->pieceUploadSpeed, sizeof( upStr ) );
136
137    if( haveDown && haveUp )
138        /* Translators: "speed|" is here for disambiguation.  Please remove it from your translation.
139           %1$s is the download speed
140           %2$s is the upload speed */
141        g_snprintf( buf, buflen, Q_(
142                        "speed|Down: %1$s, Up: %2$s" ), downStr, upStr );
143    else if( haveDown )
144        /* download speed */
145        g_snprintf( buf, buflen, _( "Down: %s" ), downStr );
146    else if( haveUp )
147        /* upload speed */
148        g_snprintf( buf, buflen, _( "Up: %s" ), upStr );
149    else
150        /* the torrent isn't uploading or downloading */
151        g_strlcpy( buf, _( "Idle" ), buflen );
152
153    return buf;
154}
155
156static char*
157getShortStatusString( const tr_stat * torStat )
158{
159    GString * gstr = g_string_new( NULL );
160
161    switch( torStat->activity )
162    {
163        case TR_STATUS_STOPPED:
164            g_string_assign( gstr, _( "Paused" ) );
165            break;
166
167        case TR_STATUS_CHECK_WAIT:
168            g_string_assign( gstr, _( "Waiting to verify local data" ) );
169            break;
170
171        case TR_STATUS_CHECK:
172            g_string_append_printf( gstr,
173                                    _(
174                                        "Verifying local data (%.1f%% tested)" ),
175                                    torStat->recheckProgress * 100.0 );
176            break;
177
178        case TR_STATUS_DOWNLOAD:
179        case TR_STATUS_SEED:
180        {
181            char buf[128];
182            if( torStat->activity != TR_STATUS_DOWNLOAD )
183            {
184                tr_strlratio( buf, torStat->ratio, sizeof( buf ) );
185                g_string_append_printf( gstr, _( "Ratio: %s" ), buf );
186                g_string_append( gstr, ", " );
187            }
188            getShortTransferString( torStat, buf, sizeof( buf ) );
189            g_string_append( gstr, buf );
190            break;
191        }
192
193        default:
194            break;
195    }
196
197    return g_string_free( gstr, FALSE );
198}
199
200static char*
201getStatusString( const tr_stat * torStat )
202{
203    const int isActive = torStat->activity != TR_STATUS_STOPPED;
204    const int isChecking = torStat->activity == TR_STATUS_CHECK
205                        || torStat->activity == TR_STATUS_CHECK_WAIT;
206
207    GString * gstr = g_string_new( NULL );
208
209    if( torStat->error )
210    {
211        g_string_assign( gstr, torStat->errorString );
212    }
213    else switch( torStat->activity )
214        {
215            case TR_STATUS_STOPPED:
216            case TR_STATUS_CHECK_WAIT:
217            case TR_STATUS_CHECK:
218            {
219                char * pch = getShortStatusString( torStat );
220                g_string_assign( gstr, pch );
221                g_free( pch );
222                break;
223            }
224
225            case TR_STATUS_DOWNLOAD:
226                g_string_append_printf( gstr,
227                    ngettext( "Downloading from %1$'d of %2$'d connected peer",
228                              "Downloading from %1$'d of %2$'d connected peers",
229                              torStat->peersConnected ),
230                    torStat->peersSendingToUs +
231                    torStat->webseedsSendingToUs,
232                    torStat->peersConnected +
233                    torStat->webseedsSendingToUs );
234                break;
235
236            case TR_STATUS_SEED:
237                g_string_append_printf( gstr,
238                    ngettext( "Seeding to %1$'d of %2$'d connected peer",
239                              "Seeding to %1$'d of %2$'d connected peers",
240                              torStat->peersConnected ),
241                    torStat->peersGettingFromUs,
242                    torStat->peersConnected );
243                break;
244        }
245
246    if( isActive && !isChecking )
247    {
248        char buf[256];
249        getShortTransferString( torStat, buf, sizeof( buf ) );
250        g_string_append_printf( gstr, " - %s", buf );
251    }
252
253    return g_string_free( gstr, FALSE );
254}
255
256/***
257****
258***/
259
260static GtkCellRendererClass * parent_class = NULL;
261
262struct TorrentCellRendererPrivate
263{
264    tr_torrent *       tor;
265    GtkCellRenderer *  text_renderer;
266    GtkCellRenderer *  text_renderer_err;
267    GtkCellRenderer *  progress_renderer;
268    int                bar_height;
269    gboolean           minimal;
270};
271
272static void
273torrent_cell_renderer_get_size( GtkCellRenderer * cell,
274                                GtkWidget *       widget,
275                                GdkRectangle *    cell_area,
276                                gint *            x_offset,
277                                gint *            y_offset,
278                                gint *            width,
279                                gint *            height )
280{
281    TorrentCellRenderer * self = TORRENT_CELL_RENDERER( cell );
282
283    if( self && self->priv->tor )
284    {
285        const tr_torrent *                  tor = self->priv->tor;
286        const tr_info *                     info = tr_torrentInfo( tor );
287        const char *                        name = info->name;
288        const tr_stat *                     torStat =
289            tr_torrentStatCached( (tr_torrent*)tor );
290        char *                              str;
291        int                                 w = 0, h = 0;
292        struct TorrentCellRendererPrivate * p = self->priv;
293        GtkCellRenderer *                   text_renderer =
294            torStat->error != 0
295            ? p->
296            text_renderer_err
297            : p->
298            text_renderer;
299
300        g_object_set( text_renderer, "ellipsize", PANGO_ELLIPSIZE_NONE,
301                      NULL );
302
303        /* above the progressbar */
304        if( p->minimal )
305        {
306            int    w1, w2, h1, h2;
307            char * shortStatus = getShortStatusString( torStat );
308            g_object_set( text_renderer, "text", name, NULL );
309            gtk_cell_renderer_get_size( text_renderer,
310                                        widget, NULL, NULL, NULL, &w1, &h1 );
311            str = g_markup_printf_escaped( "<small>%s</small>", shortStatus );
312            g_object_set( text_renderer, "markup", str, NULL );
313            gtk_cell_renderer_get_size( text_renderer,
314                                        widget, NULL, NULL, NULL, &w2, &h2 );
315            h += MAX( h1, h2 );
316            w = MAX( w, w1 + GUI_PAD_BIG + w2 );
317            g_free( str );
318            g_free( shortStatus );
319        }
320        else
321        {
322            int    w1, h1;
323            char * progressString = getProgressString( tor, info, torStat );
324            str = g_markup_printf_escaped( "<b>%s</b>\n<small>%s</small>",
325                                           name, progressString );
326            g_object_set( text_renderer, "markup", str, NULL );
327            gtk_cell_renderer_get_size( text_renderer,
328                                        widget, NULL, NULL, NULL, &w1, &h1 );
329            h += h1;
330            w = MAX( w, w1 );
331            g_free( str );
332            g_free( progressString );
333        }
334
335        /* below the progressbar */
336        if( !p->minimal )
337        {
338            int    w1, h1;
339            char * statusString = getStatusString( torStat );
340            str = g_markup_printf_escaped( "<small>%s</small>",
341                                           statusString );
342            g_object_set( text_renderer, "markup", str, NULL );
343            gtk_cell_renderer_get_size( text_renderer,
344                                        widget, NULL, NULL, NULL, &w1, &h1 );
345            h += h1;
346            w = MAX( w, w1 );
347            g_free( str );
348            g_free( statusString );
349        }
350
351        h += p->bar_height;
352
353        if( cell_area )
354        {
355            if( x_offset ) *x_offset = 0;
356            if( y_offset )
357            {
358                *y_offset = 0.5 *
359                            ( cell_area->height - ( h + ( 2 * cell->ypad ) ) );
360                *y_offset = MAX( *y_offset, 0 );
361            }
362        }
363
364        *width = w + cell->xpad * 2;
365        *height = h + cell->ypad * 2;
366    }
367}
368
369static void
370torrent_cell_renderer_render(
371    GtkCellRenderer *                  cell,
372    GdkDrawable *                      window,
373    GtkWidget *                        widget,
374    GdkRectangle *
375                                       background_area,
376    GdkRectangle         * cell_area   UNUSED,
377    GdkRectangle         * expose_area UNUSED,
378    GtkCellRendererState               flags )
379{
380    TorrentCellRenderer * self = TORRENT_CELL_RENDERER( cell );
381
382#ifdef TEST_RTL
383    GtkTextDirection      real_dir = gtk_widget_get_direction( widget );
384    gtk_widget_set_direction( widget, GTK_TEXT_DIR_RTL );
385#endif
386
387    if( self && self->priv->tor )
388    {
389        const tr_torrent *                  tor = self->priv->tor;
390        const tr_info *                     info = tr_torrentInfo( tor );
391        const char *                        name = info->name;
392        const tr_stat *                     torStat =
393            tr_torrentStatCached( (tr_torrent*)tor );
394        GdkRectangle                        my_bg;
395        GdkRectangle                        my_cell;
396        GdkRectangle                        my_expose;
397        int                                 w, h;
398        struct TorrentCellRendererPrivate * p = self->priv;
399        GtkCellRenderer * text_renderer = torStat->error != 0
400                                        ? p->text_renderer_err
401                                        : p->text_renderer;
402        const gboolean isActive = torStat->activity != TR_STATUS_STOPPED;
403
404        my_bg = *background_area;
405        my_bg.x += cell->xpad;
406        my_bg.y += cell->ypad;
407        my_bg.width -= cell->xpad * 2;
408        my_cell = my_expose = my_bg;
409
410        g_object_set( text_renderer, "sensitive", isActive, NULL );
411        g_object_set( p->progress_renderer, "sensitive", isActive, NULL );
412
413        /* above the progressbar */
414        if( !p->minimal )
415        {
416            char * progressString = getProgressString( tor, info, torStat );
417            char * str = g_markup_printf_escaped(
418                "<b>%s</b>\n<small>%s</small>",
419                name, progressString );
420            g_object_set( text_renderer, "markup", str,
421                          "ellipsize", PANGO_ELLIPSIZE_NONE,
422                          NULL );
423            gtk_cell_renderer_get_size( text_renderer,
424                                        widget, NULL, NULL, NULL, &w, &h );
425            my_bg.height     =
426                my_cell.height   =
427                    my_expose.height = h;
428            g_object_set( text_renderer, "ellipsize", PANGO_ELLIPSIZE_END,
429                          NULL );
430            gtk_cell_renderer_render( text_renderer,
431                                      window, widget,
432                                      &my_bg, &my_cell, &my_expose, flags );
433            my_bg.y += h;
434            my_cell.y += h;
435            my_expose.y += h;
436
437            g_free( str );
438            g_free( progressString );
439        }
440        else
441        {
442            char *       statusStr = getShortStatusString( torStat );
443            char *       str = g_markup_printf_escaped( "<small>%s</small>",
444                                                        statusStr );
445            int          w1, w2, h1, h2, tmp_h;
446            GdkRectangle tmp_bg, tmp_cell, tmp_expose;
447
448            /* get the dimensions for the name */
449            g_object_set( text_renderer, "text", name,
450                          "ellipsize", PANGO_ELLIPSIZE_NONE,
451                          NULL );
452            gtk_cell_renderer_get_size( text_renderer,
453                                        widget, NULL, NULL, NULL, &w1, &h1 );
454
455            /* get the dimensions for the short status string */
456            g_object_set( text_renderer, "markup", str,
457                          "ellipsize", PANGO_ELLIPSIZE_NONE,
458                          NULL );
459            gtk_cell_renderer_get_size( text_renderer,
460                                        widget, NULL, NULL, NULL, &w2, &h2 );
461
462            tmp_h = MAX( h1, h2 );
463
464            /* short status */
465            tmp_bg.x = my_bg.width - w2;
466            tmp_bg.y = my_bg.y + ( h2 - h1 ) / 2;
467            tmp_bg.width = w2;
468            tmp_bg.height = tmp_h;
469            tmp_expose = tmp_cell = tmp_bg;
470            g_object_set( text_renderer, "markup", str,
471                          "ellipsize", PANGO_ELLIPSIZE_END,
472                          NULL );
473            gtk_cell_renderer_render( text_renderer,
474                                      window, widget,
475                                      &tmp_bg, &tmp_cell, &tmp_expose,
476                                      flags );
477
478            /* name */
479            tmp_bg.x = my_bg.x;
480            tmp_bg.width = my_bg.width - w2 - GUI_PAD_BIG;
481            tmp_expose = tmp_cell = tmp_bg;
482            g_object_set( text_renderer, "text", name,
483                          "ellipsize", PANGO_ELLIPSIZE_END,
484                          NULL );
485            gtk_cell_renderer_render( text_renderer,
486                                      window, widget,
487                                      &tmp_bg, &tmp_cell, &tmp_expose,
488                                      flags );
489
490            my_bg.y = tmp_bg.y + tmp_bg.height;
491            my_cell.y = tmp_cell.y + tmp_cell.height;
492            my_expose.y = tmp_expose.y + tmp_cell.height;
493
494            g_free( str );
495            g_free( statusStr );
496        }
497
498        /* the progressbar */
499        my_cell.height = p->bar_height;
500        if( 1 )
501        {
502            const double percent = MAX( 0.0, torStat->percentDone );
503            g_object_set( p->progress_renderer, "value",
504                          (int)( percent * 100.0 ),
505                          "text", "",
506                          NULL );
507            gtk_cell_renderer_render( p->progress_renderer,
508                                      window, widget,
509                                      &my_cell, &my_cell, &my_cell, flags );
510        }
511        my_bg.y     += my_cell.height;
512        my_cell.y   += my_cell.height;
513        my_expose.y += my_cell.height;
514
515        /* below progressbar */
516        if( !p->minimal )
517        {
518            char * statusString = getStatusString( torStat );
519            char * str = g_markup_printf_escaped( "<small>%s</small>",
520                                                  statusString );
521            g_object_set( text_renderer, "markup", str,
522                          "ellipsize", PANGO_ELLIPSIZE_END,
523                          NULL );
524            gtk_cell_renderer_get_size( text_renderer,
525                                        widget, NULL, NULL, NULL, &w, &h );
526            my_bg.height      =
527                my_cell.height    =
528                    my_expose.height  = h;
529            gtk_cell_renderer_render( text_renderer,
530                                      window, widget,
531                                      &my_bg, &my_cell, &my_expose, flags );
532
533            g_free( str );
534            g_free( statusString );
535        }
536    }
537
538#ifdef TEST_RTL
539    gtk_widget_set_direction( widget, real_dir );
540#endif
541}
542
543static void
544torrent_cell_renderer_set_property( GObject *      object,
545                                    guint          property_id,
546                                    const GValue * v,
547                                    GParamSpec *   pspec )
548{
549    TorrentCellRenderer *               self = TORRENT_CELL_RENDERER(
550        object );
551    struct TorrentCellRendererPrivate * p = self->priv;
552
553    switch( property_id )
554    {
555        case P_TORRENT:
556            p->tor = g_value_get_pointer( v ); break;
557
558        case P_BAR_HEIGHT:
559            p->bar_height = g_value_get_int( v ); break;
560
561        case P_MINIMAL:
562            p->minimal  = g_value_get_boolean( v ); break;
563
564        default:
565            G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, pspec );
566            break;
567    }
568}
569
570static void
571torrent_cell_renderer_get_property( GObject *    object,
572                                    guint        property_id,
573                                    GValue *     v,
574                                    GParamSpec * pspec )
575{
576    const TorrentCellRenderer *         self = TORRENT_CELL_RENDERER(
577        object );
578    struct TorrentCellRendererPrivate * p = self->priv;
579
580    switch( property_id )
581    {
582        case P_TORRENT:
583            g_value_set_pointer( v, p->tor ); break;
584
585        case P_BAR_HEIGHT:
586            g_value_set_int( v, p->bar_height ); break;
587
588        case P_MINIMAL:
589            g_value_set_boolean( v, p->minimal ); break;
590
591        default:
592            G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, pspec );
593            break;
594    }
595}
596
597static void
598torrent_cell_renderer_dispose( GObject * o )
599{
600    TorrentCellRenderer * r = TORRENT_CELL_RENDERER( o );
601    GObjectClass *        parent;
602
603    if( r && r->priv )
604    {
605        g_object_unref( G_OBJECT( r->priv->text_renderer ) );
606        g_object_unref( G_OBJECT( r->priv->text_renderer_err ) );
607        g_object_unref( G_OBJECT( r->priv->progress_renderer ) );
608        r->priv = NULL;
609    }
610
611    parent = g_type_class_peek( g_type_parent( TORRENT_CELL_RENDERER_TYPE ) );
612    parent->dispose( o );
613}
614
615static void
616torrent_cell_renderer_class_init( TorrentCellRendererClass * klass )
617{
618    GObjectClass *         gobject_class = G_OBJECT_CLASS( klass );
619    GtkCellRendererClass * cell_class = GTK_CELL_RENDERER_CLASS( klass );
620
621    g_type_class_add_private( klass,
622                             sizeof( struct TorrentCellRendererPrivate ) );
623
624    parent_class = (GtkCellRendererClass*) g_type_class_peek_parent( klass );
625
626    cell_class->render = torrent_cell_renderer_render;
627    cell_class->get_size = torrent_cell_renderer_get_size;
628    gobject_class->set_property = torrent_cell_renderer_set_property;
629    gobject_class->get_property = torrent_cell_renderer_get_property;
630    gobject_class->dispose = torrent_cell_renderer_dispose;
631
632    g_object_class_install_property( gobject_class, P_TORRENT,
633                                    g_param_spec_pointer( "torrent", NULL,
634                                                          "tr_torrent*",
635                                                          G_PARAM_READWRITE ) );
636
637    g_object_class_install_property( gobject_class, P_BAR_HEIGHT,
638                                    g_param_spec_int( "bar-height", NULL,
639                                                      "Bar Height",
640                                                      1, INT_MAX,
641                                                      DEFAULT_BAR_HEIGHT,
642                                                      G_PARAM_READWRITE ) );
643
644    g_object_class_install_property( gobject_class, P_MINIMAL,
645                                    g_param_spec_boolean( "minimal", NULL,
646                                                          "Minimal Mode",
647                                                          FALSE,
648                                                          G_PARAM_READWRITE ) );
649}
650
651static void
652torrent_cell_renderer_init( GTypeInstance *  instance,
653                            gpointer g_class UNUSED )
654{
655    TorrentCellRenderer *               self = TORRENT_CELL_RENDERER(
656        instance );
657    struct TorrentCellRendererPrivate * p;
658
659    p = self->priv = G_TYPE_INSTANCE_GET_PRIVATE(
660            self,
661            TORRENT_CELL_RENDERER_TYPE,
662            struct
663            TorrentCellRendererPrivate );
664
665    p->tor = NULL;
666    p->text_renderer = gtk_cell_renderer_text_new( );
667    p->text_renderer_err = gtk_cell_renderer_text_new(  );
668    p->progress_renderer = gtk_cell_renderer_progress_new(  );
669    g_object_set( p->text_renderer_err, "foreground", "red", NULL );
670    tr_object_ref_sink( p->text_renderer );
671    tr_object_ref_sink( p->text_renderer_err );
672    tr_object_ref_sink( p->progress_renderer );
673
674    p->bar_height = DEFAULT_BAR_HEIGHT;
675}
676
677GType
678torrent_cell_renderer_get_type( void )
679{
680    static GType type = 0;
681
682    if( !type )
683    {
684        static const GTypeInfo info =
685        {
686            sizeof( TorrentCellRendererClass ),
687            NULL,                                            /* base_init */
688            NULL,                                            /* base_finalize */
689            (GClassInitFunc)torrent_cell_renderer_class_init,
690            NULL,                                            /* class_finalize
691                                                               */
692            NULL,                                            /* class_data */
693            sizeof( TorrentCellRenderer ),
694            0,                                               /* n_preallocs */
695            (GInstanceInitFunc)torrent_cell_renderer_init,
696            NULL
697        };
698
699        type = g_type_register_static( GTK_TYPE_CELL_RENDERER,
700                                       "TorrentCellRenderer",
701                                       &info, (GTypeFlags)0 );
702    }
703
704    return type;
705}
706
707GtkCellRenderer *
708torrent_cell_renderer_new( void )
709{
710    return (GtkCellRenderer *) g_object_new( TORRENT_CELL_RENDERER_TYPE,
711                                             NULL );
712}
713
Note: See TracBrowser for help on using the repository browser.