Changeset 1475


Ignore:
Timestamp:
Feb 7, 2007, 7:35:33 AM (16 years ago)
Author:
joshe
Message:

Split off the window-related code into a new file.
Bump a couple copyright dates I forgot earlier.

Location:
trunk
Files:
2 added
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/gtk/conf.h

    r1468 r1475  
    22 * $Id$
    33 *
    4  * Copyright (c) 2005-2006 Transmission authors and contributors
     4 * Copyright (c) 2005-2007 Transmission authors and contributors
    55 *
    66 * Permission is hereby granted, free of charge, to any person obtaining a
  • trunk/gtk/dialogs.h

    r1468 r1475  
    22 * $Id$
    33 *
    4  * Copyright (c) 2005-2006 Transmission authors and contributors
     4 * Copyright (c) 2005-2007 Transmission authors and contributors
    55 *
    66 * Permission is hereby granted, free of charge, to any person obtaining a
  • trunk/gtk/main.c

    r1472 r1475  
    22 * $Id$
    33 *
    4  * Copyright (c) 2005-2006 Transmission authors and contributors
     4 * Copyright (c) 2005-2007 Transmission authors and contributors
    55 *
    66 * Permission is hereby granted, free of charge, to any person obtaining a
     
    4343#include "tr_torrent.h"
    4444#include "tr_cell_renderer_progress.h"
     45#include "tr_window.h"
    4546#include "transmission.h"
    4647#include "util.h"
     
    6162  GtkWindow *wind;
    6263  GtkTreeModel *model;
    63   GtkTreeView *view;
    64   GtkStatusbar *bar;
    65   GtkWidget **buttons;
    6664  guint timer;
    6765  gboolean prefsopen;
    6866  gboolean msgwinopen;
    69   GtkWidget *stupidpopuphack;
    7067  gboolean closing;
    7168};
     
    7774};
    7875
    79 GList *
     76enum action
     77{
     78    ACT_OPEN = 0,
     79    ACT_START,
     80    ACT_STOP,
     81    ACT_DELETE,
     82    ACT_INFO,
     83    ACT_PREF,
     84    ACT_DEBUG,
     85    ACTION_COUNT,
     86};
     87
     88struct
     89{
     90    const char * label;
     91    const char * icon;
     92    int          flags;
     93    const char * tooltip;
     94}
     95actions[] =
     96{
     97    { N_("Add"),         GTK_STOCK_ADD,         ACTF_WHEREVER | ACTF_ALWAYS,
     98      N_("Add a new torrent") },
     99    { N_("Start"),       GTK_STOCK_EXECUTE,     ACTF_WHEREVER | ACTF_INACTIVE,
     100      N_("Start a torrent that is not running") },
     101    { N_("Stop"),        GTK_STOCK_STOP,        ACTF_WHEREVER | ACTF_ACTIVE,
     102      N_("Stop a torrent that is running") },
     103    { N_("Remove"),      GTK_STOCK_REMOVE,      ACTF_WHEREVER | ACTF_WHATEVER,
     104      N_("Remove a torrent") },
     105    { N_("Properties"),  GTK_STOCK_PROPERTIES,  ACTF_WHEREVER | ACTF_WHATEVER,
     106      N_("Show additional information about a torrent") },
     107    { N_("Preferences"), GTK_STOCK_PREFERENCES, ACTF_WHEREVER | ACTF_ALWAYS,
     108      N_("Customize application behavior") },
     109    { N_("Open debug window"), NULL,            ACTF_MENU     | ACTF_ALWAYS,
     110      NULL },
     111};
     112
     113#define CBDATA_PTR              "callback-data-pointer"
     114
     115#define SIGCOUNT_MAX            3
     116
     117static sig_atomic_t global_sigcount = 0;
     118
     119static GList *
    80120readargs(int argc, char **argv);
    81121
    82 void
    83 makewind(GtkWidget *wind, TrBackend *back, benc_val_t *state, GList *args);
    84 void
     122static void
     123makewind(TrWindow *wind, TrBackend *back, benc_val_t *state, GList *args);
     124static void
    85125quittransmission(struct cbdata *data);
    86 GtkWidget *
    87 makewind_toolbar(struct cbdata *data);
    88 GtkWidget *
    89 makewind_list(struct cbdata *data, GObject **sizehack);
    90 gboolean
     126static gboolean
    91127winclose(GtkWidget *widget, GdkEvent *event, gpointer gdata);
    92 gboolean
     128static gboolean
    93129exitcheck(gpointer gdata);
    94 void
     130static void
    95131setupdrag(GtkWidget *widget, struct cbdata *data);
    96 void
     132static void
    97133gotdrag(GtkWidget *widget, GdkDragContext *dc, gint x, gint y,
    98134        GtkSelectionData *sel, guint info, guint time, gpointer gdata);
    99 static void
    100 stylekludge(GObject *obj, GParamSpec *spec, gpointer gdata);
    101 void
    102 fixbuttons(GtkTreeSelection *sel, gpointer gdata);
    103 void
    104 dfname(GtkTreeViewColumn *col, GtkCellRenderer *rend, GtkTreeModel *model,
    105        GtkTreeIter *iter, gpointer gdata);
    106 void
    107 dfprog(GtkTreeViewColumn *col, GtkCellRenderer *rend, GtkTreeModel *model,
    108        GtkTreeIter *iter, gpointer gdata);
    109 
    110 gboolean
     135
     136static gboolean
    111137updatemodel(gpointer gdata);
    112 gboolean
    113 listclick(GtkWidget *widget, GdkEventButton *event, gpointer gdata);
    114 gboolean
    115 listpopup(GtkWidget *widget, gpointer gdata);
    116 void
    117 dopopupmenu(GdkEventButton *event, struct cbdata *data);
    118 void
     138static void
    119139boolwindclosed(GtkWidget *widget SHUTUP, gpointer gdata);
    120 void
    121 actionclick(GtkWidget *widget, gpointer gdata);
    122 gint
    123 intrevcmp(gconstpointer a, gconstpointer b);
    124 void
    125 doubleclick(GtkWidget *widget, GtkTreePath *path, GtkTreeViewColumn *col,
    126             gpointer gdata);
    127 
    128 void
     140static void
     141windact(GtkWidget *widget, int action, gpointer gdata);
     142static void
     143handleaction(struct cbdata *data, enum action action);
     144
     145static void
    129146addtorrents(void *vdata, void *state, GList *files,
    130147            const char *dir, guint flags);
    131 void
     148static void
    132149savetorrents(struct cbdata *data);
    133 void
    134 orstatus(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter,
    135          gpointer gdata);
    136 void
    137 istorsel(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter,
    138          gpointer gdata);
    139 void
     150static void
    140151safepipe(void);
    141 void
     152static void
    142153setupsighandlers(void);
    143 void
     154static void
    144155fatalsig(int sig);
    145 
    146 #define LIST_ACTION           "torrent-list-action"
    147 enum listact {
    148   ACT_OPEN, ACT_START, ACT_STOP, ACT_DELETE, ACT_INFO, ACT_PREF, ACT_DEBUG };
    149 
    150 struct { const gchar *name; const gchar *id; enum listact act; gboolean nomenu;
    151   int avail; const char *ttext; const char *tpriv; }
    152 actionitems[] = {
    153   {N_("Add"),         GTK_STOCK_ADD,          ACT_OPEN,   FALSE,  0,
    154    N_("Add a new torrent"), "XXX"},
    155   {N_("Start"),       GTK_STOCK_EXECUTE,      ACT_START,  FALSE,
    156    TR_STATUS_INACTIVE,
    157    N_("Start a torrent that is not running"), "XXX"},
    158   {N_("Stop"),        GTK_STOCK_STOP,         ACT_STOP,   FALSE,
    159    TR_STATUS_ACTIVE,
    160    N_("Stop a torrent that is running"), "XXX"},
    161   {N_("Remove"),      GTK_STOCK_REMOVE,       ACT_DELETE, FALSE, ~0,
    162    N_("Remove a torrent"), "XXX"},
    163   {N_("Properties"),  GTK_STOCK_PROPERTIES,   ACT_INFO,   FALSE, ~0,
    164    N_("Show additional information about a torrent"), "XXX"},
    165   {N_("Preferences"), GTK_STOCK_PREFERENCES,  ACT_PREF,   TRUE,   0,
    166    N_("Customize application behavior"), "XXX"},
    167   {N_("Open debug window"), NULL, ACT_DEBUG,  FALSE,  0, NULL, NULL},
    168 };
    169 
    170 #define CBDATA_PTR              "callback-data-pointer"
    171 
    172 #define SIGCOUNT_MAX            3
    173 
    174 static sig_atomic_t global_sigcount = 0;
    175156
    176157int
     
    225206
    226207      /* create main window now so any error dialogs can be it's children */
    227       mainwind = gtk_window_new(GTK_WINDOW_TOPLEVEL);
     208      mainwind = tr_window_new();
    228209      preferr = NULL;
    229210      stateerr = NULL;
     
    248229      applyprefs(back);
    249230
    250       makewind(mainwind, back, state, argfiles);
     231      makewind( TR_WINDOW( mainwind ), back, state, argfiles );
    251232
    252233      if(NULL != state)
     
    307288}
    308289
    309 void
    310 makewind(GtkWidget *wind, TrBackend *back, benc_val_t *state, GList *args) {
    311   GtkWidget *vbox = gtk_vbox_new(FALSE, 0);
    312   GtkWidget *scroll = gtk_scrolled_window_new(NULL, NULL);
    313   GtkWidget *status = gtk_statusbar_new();
    314   struct cbdata *data = g_new0(struct cbdata, 1);
    315   GtkWidget *list;
    316   GtkRequisition req;
    317   gint width, height;
    318   GObject *sizehack;
    319   GdkScreen *screen;
    320 
    321   g_object_ref(G_OBJECT(back));
    322   data->back = back;
    323   data->wind = GTK_WINDOW(wind);
    324   data->timer = 0;
    325   /* filled in by makewind_list */
    326   data->model = NULL;
    327   data->view = NULL;
    328   data->bar = GTK_STATUSBAR(status);
    329   data->buttons = NULL;
    330   data->prefsopen = FALSE;
    331   data->msgwinopen = FALSE;
    332   data->stupidpopuphack = NULL;
    333   data->closing = FALSE;
    334 
    335   gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_NEVER,
    336                                  GTK_POLICY_ALWAYS);
    337 
    338   gtk_box_pack_start(GTK_BOX(vbox), makewind_toolbar(data), FALSE, FALSE, 0);
    339 
    340   sizehack = NULL;
    341   list = makewind_list(data, &sizehack);
    342   gtk_container_add(GTK_CONTAINER(scroll), list);
    343   gtk_box_pack_start(GTK_BOX(vbox), scroll, TRUE, TRUE, 0);
    344 
    345   gtk_statusbar_push(GTK_STATUSBAR(status), 0, "");
    346   gtk_box_pack_start(GTK_BOX(vbox), status, FALSE, FALSE, 0);
    347 
    348   gtk_container_set_focus_child(GTK_CONTAINER(vbox), scroll);
    349   gtk_container_add(GTK_CONTAINER(wind), vbox);
    350   gtk_window_set_title(data->wind, g_get_application_name());
    351   g_signal_connect(G_OBJECT(wind), "delete_event", G_CALLBACK(winclose), data);
    352 
    353   setupdrag(list, data);
    354 
    355   addtorrents(data, state, args, NULL, addactionflag(cf_getpref(PREF_ADDIPC)));
    356 
    357   data->timer = g_timeout_add(UPDATE_INTERVAL, updatemodel, data);
    358   updatemodel(data);
    359 
    360   /* some evil magic to try to get a nice initial window size */
    361   gtk_widget_show_all(vbox);
    362   gtk_widget_realize(wind);
    363   gtk_widget_size_request(list, &req);
    364   height = req.height;
    365   gtk_widget_size_request(scroll, &req);
    366   height -= req.height;
    367   gtk_widget_size_request(wind, &req);
    368   height += req.height;
    369   screen = gtk_widget_get_screen(wind);
    370   width = MIN(req.width, gdk_screen_get_width(screen) / 2);
    371   height = MIN(height, gdk_screen_get_height(screen) / 5 * 4);
    372   if(height > req.width)
    373     height = MIN(height, width * 8 / 5);
    374   else
    375     height = MAX(height, width * 5 / 8);
    376   height = (height > req.width ?
    377             MIN(height, width * 8 / 5) : MAX(height, width * 5 / 8));
    378   g_object_set(sizehack, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
    379   gtk_widget_show_now(wind);
    380   gtk_window_resize(GTK_WINDOW(wind), width, height);
    381 
    382   /* set up the ipc socket now that we're ready to get torrents from it */
    383   ipc_socket_setup(GTK_WINDOW(wind), addtorrents, data);
    384 }
    385 
    386 void
    387 quittransmission(struct cbdata *data) {
    388   g_object_unref(G_OBJECT(data->back));
    389   gtk_widget_destroy(GTK_WIDGET(data->wind));
    390   if(0 < data->timer)
    391     g_source_remove(data->timer);
    392   if(NULL != data->stupidpopuphack)
    393     gtk_widget_destroy(data->stupidpopuphack);
    394   g_free(data->buttons);
    395   g_free(data);
    396   gtk_main_quit();
    397 }
    398 
    399 GtkWidget *
    400 makewind_toolbar(struct cbdata *data) {
    401   GtkWidget *bar = gtk_toolbar_new();
    402   GtkToolItem *item;
    403   unsigned int ii;
    404 
    405   gtk_toolbar_set_tooltips(GTK_TOOLBAR(bar), TRUE);
    406   gtk_toolbar_set_show_arrow(GTK_TOOLBAR(bar), FALSE);
    407 
    408   data->buttons = g_new(GtkWidget*, ALEN(actionitems));
    409 
    410   for(ii = 0; ii < ALEN(actionitems); ii++) {
    411     if( NULL == actionitems[ii].id ) {
    412       data->buttons[ii] = NULL;
    413       continue;
    414     }
    415     item = gtk_tool_button_new_from_stock(actionitems[ii].id);
    416     data->buttons[ii] = GTK_WIDGET(item);
    417     gtk_tool_button_set_label(GTK_TOOL_BUTTON(item),
    418                               gettext(actionitems[ii].name));
    419     gtk_tool_item_set_tooltip(GTK_TOOL_ITEM(item), GTK_TOOLBAR(bar)->tooltips,
    420                               gettext(actionitems[ii].ttext),
    421                               actionitems[ii].tpriv);
    422     g_object_set_data(G_OBJECT(item), LIST_ACTION,
    423                       GINT_TO_POINTER(actionitems[ii].act));
    424     g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(actionclick), data);
    425     gtk_toolbar_insert(GTK_TOOLBAR(bar), item, -1);
    426   }
    427 
    428   return bar;
    429 }
    430 
    431 /* XXX check for unused data in model */
    432 enum {
    433   MC_NAME, MC_SIZE, MC_STAT, MC_ERR, MC_TERR,
    434   MC_PROG, MC_DRATE, MC_URATE, MC_ETA, MC_PEERS,
    435   MC_UPEERS, MC_DPEERS, MC_DOWN, MC_UP,
    436   MC_TORRENT, MC_ROW_COUNT,
    437 };
    438 
    439 GtkWidget *
    440 makewind_list(struct cbdata *data, GObject **sizehack) {
     290static void
     291makewind( TrWindow * wind, TrBackend * back, benc_val_t * state, GList * args)
     292{
    441293  GType types[] = {
    442294    /* info->name, info->totalSize, status,     error,      errorString, */
     
    448300    /* the torrent object */
    449301    TR_TORRENT_TYPE};
     302  struct cbdata *data = g_new0(struct cbdata, 1);
    450303  GtkListStore *store;
    451   GtkWidget *view;
    452   GtkTreeViewColumn *col;
    453   GtkTreeSelection *sel;
    454   GtkCellRenderer *namerend, *progrend;
    455   char *str;
     304  unsigned int ii;
     305  GtkWidget *drag;
    456306
    457307  g_assert(MC_ROW_COUNT == ALEN(types));
    458 
    459308  store = gtk_list_store_newv(MC_ROW_COUNT, types);
    460   view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
    461   /* XXX do I need to worry about reference counts anywhere else? */
    462   g_object_unref(G_OBJECT(store));
     309
     310  g_object_ref(G_OBJECT(back));
     311  data->back = back;
     312  data->wind = GTK_WINDOW(wind);
     313  data->timer = 0;
    463314  data->model = GTK_TREE_MODEL(store);
    464   data->view = GTK_TREE_VIEW(view);
    465 
    466   namerend = gtk_cell_renderer_text_new();
    467   *sizehack = G_OBJECT(namerend);
    468   /* note that this renderer is set to ellipsize, just not here */
    469   col = gtk_tree_view_column_new_with_attributes(_("Name"), namerend, NULL);
    470   gtk_tree_view_column_set_cell_data_func(col, namerend, dfname, NULL, NULL);
    471   gtk_tree_view_column_set_expand(col, TRUE);
    472   gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
    473   gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);
    474 
    475   progrend = tr_cell_renderer_progress_new();
    476   /* this string is only used to determing the size of the progress bar */
    477   str = g_markup_printf_escaped("<big>%s</big>", _("  fnord    fnord  "));
    478   g_object_set(progrend, "bar-sizing", str, NULL);
    479   g_free(str);
    480   col = gtk_tree_view_column_new_with_attributes(_("Progress"), progrend, NULL);
    481   gtk_tree_view_column_set_cell_data_func(col, progrend, dfprog, NULL, NULL);
    482   gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
    483   gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);
    484 
    485   /* XXX this shouldn't be necessary */
    486   g_signal_connect(view, "notify", G_CALLBACK(stylekludge), progrend);
    487 
    488   gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(view), TRUE);
    489   sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
    490   gtk_tree_selection_set_mode(GTK_TREE_SELECTION(sel), GTK_SELECTION_MULTIPLE);
    491   g_signal_connect(G_OBJECT(sel), "changed", G_CALLBACK(fixbuttons), data);
    492   g_signal_connect(G_OBJECT(view), "button-press-event",
    493                    G_CALLBACK(listclick), data);
    494   g_signal_connect(G_OBJECT(view), "popup-menu", G_CALLBACK(listpopup), data);
    495   g_signal_connect(G_OBJECT(view), "row-activated",
    496                    G_CALLBACK(doubleclick), data);
    497   gtk_widget_show_all(view);
    498 
    499   return view;
     315  data->prefsopen = FALSE;
     316  data->msgwinopen = FALSE;
     317  data->closing = FALSE;
     318
     319  g_assert( ACTION_COUNT == ALEN( actions ) );
     320  for( ii = 0; ii < ALEN( actions ); ii++ )
     321  {
     322      tr_window_action_add( wind, ii, actions[ii].flags,
     323                            gettext( actions[ii].label ),
     324                            actions[ii].icon,
     325                            gettext( actions[ii].tooltip ) );
     326  }
     327  g_object_set( wind, "model", data->model,
     328                      "double-click-action", ACT_INFO, NULL);
     329
     330  g_signal_connect( wind, "action",       G_CALLBACK( windact  ), data );
     331  g_signal_connect( wind, "delete_event", G_CALLBACK( winclose ), data );
     332
     333  g_object_get( wind, "drag-widget", &drag, NULL );
     334  setupdrag( drag, data );
     335
     336  addtorrents(data, state, args, NULL, addactionflag(cf_getpref(PREF_ADDIPC)));
     337
     338  data->timer = g_timeout_add(UPDATE_INTERVAL, updatemodel, data);
     339  updatemodel(data);
     340
     341  /* this shows the window */
     342  tr_window_size_hack( wind );
     343
     344  /* set up the ipc socket now that we're ready to get torrents from it */
     345  ipc_socket_setup(GTK_WINDOW(wind), addtorrents, data);
     346}
     347
     348static void
     349quittransmission( struct cbdata * data )
     350{
     351    g_object_unref( G_OBJECT( data->back ) );
     352    if( NULL != data->wind )
     353    {
     354        gtk_widget_destroy( GTK_WIDGET( data->wind ) );
     355    }
     356    g_object_unref( data->model );
     357    if( 0 < data->timer )
     358    {
     359        g_source_remove( data->timer );
     360    }
     361    g_free( data );
     362    gtk_main_quit();
    500363}
    501364
     
    504367  struct cbdata *data = gdata;
    505368  struct exitdata *edata;
    506   unsigned int ii;
    507369  GtkTreeIter iter;
    508370  TrTorrent *tor;
     
    518380    Add a reference to all torrents in the list, which will be removed
    519381    when the politely-stopped signal is emitted.  This is necessary
    520     because actionclick() adds a reference when it removes a torrent
    521     from the model and calls tr_torrent_stop_polite() on it.
     382    because a reference is added when a torrent is removed
     383    from the model and tr_torrent_stop_polite() is called on it.
    522384  */
    523385  if(gtk_tree_model_get_iter_first(data->model, &iter)) {
     
    541403    /* yes, start the exit timer and disable widgets */
    542404    edata->timer = g_timeout_add(EXIT_CHECK_INTERVAL, exitcheck, edata);
    543     for(ii = 0; ii < ALEN(actionitems); ii++)
    544       if( NULL != data->buttons[ii] )
    545         gtk_widget_set_sensitive(data->buttons[ii], FALSE);
    546     gtk_widget_set_sensitive(GTK_WIDGET(data->view), FALSE);
     405    gtk_widget_set_sensitive( GTK_WIDGET( data->wind ), FALSE );
    547406  }
    548407
     
    576435}
    577436
    578 void
     437static void
    579438gotdrag(GtkWidget *widget SHUTUP, GdkDragContext *dc, gint x SHUTUP,
    580439        gint y SHUTUP, GtkSelectionData *sel, guint info SHUTUP, guint time,
     
    658517}
    659518
    660 void
     519static void
    661520setupdrag(GtkWidget *widget, struct cbdata *data) {
    662521  GtkTargetEntry targets[] = {
     
    670529  gtk_drag_dest_set(widget, GTK_DEST_DEFAULT_ALL, targets,
    671530                    ALEN(targets), GDK_ACTION_COPY | GDK_ACTION_MOVE);
    672 }
    673 
    674 /* kludge to have the progress bars notice theme changes */
    675 static void
    676 stylekludge(GObject *obj, GParamSpec *spec, gpointer gdata) {
    677   if(0 == strcmp("style", spec->name)) {
    678     tr_cell_renderer_progress_reset_style(TR_CELL_RENDERER_PROGRESS(gdata));
    679     gtk_widget_queue_draw(GTK_WIDGET(obj));
    680   }
    681 }
    682 
    683 /* disable buttons the user shouldn't be able to click on */
    684 void
    685 fixbuttons(GtkTreeSelection *sel, gpointer gdata) {
    686   struct cbdata *data = gdata;
    687   gboolean selected;
    688   unsigned int ii;
    689   int status;
    690 
    691   if(NULL == sel)
    692     sel = gtk_tree_view_get_selection(data->view);
    693   status = 0;
    694   gtk_tree_selection_selected_foreach(sel, orstatus, &status);
    695   selected = (0 < gtk_tree_selection_count_selected_rows(sel));
    696 
    697   for(ii = 0; ii < ALEN(actionitems); ii++)
    698     if(actionitems[ii].avail)
    699       gtk_widget_set_sensitive(data->buttons[ii],
    700                                (selected && (actionitems[ii].avail & status)));
    701 }
    702 
    703 void
    704 dfname(GtkTreeViewColumn *col SHUTUP, GtkCellRenderer *rend,
    705        GtkTreeModel *model, GtkTreeIter *iter, gpointer gdata SHUTUP) {
    706   char *name, *mb, *terr, *str, *top, *bottom, *timestr;
    707   guint64 size;
    708   gfloat prog;
    709   int status, err, eta, tpeers, upeers, dpeers;
    710 
    711   gtk_tree_model_get(model, iter, MC_NAME, &name, MC_STAT, &status,
    712     MC_ERR, &err, MC_SIZE, &size, MC_PROG, &prog, MC_ETA, &eta,
    713     MC_PEERS, &tpeers, MC_UPEERS, &upeers, MC_DPEERS, &dpeers, -1);
    714 
    715   if(0 > tpeers)
    716     tpeers = 0;
    717   if(0 > upeers)
    718     upeers = 0;
    719   if(0 > dpeers)
    720     dpeers = 0;
    721   mb = readablesize(size);
    722   prog *= 100;
    723 
    724   if(status & TR_STATUS_CHECK)
    725     top = g_strdup_printf(_("Checking existing files (%.1f%%)"), prog);
    726   else if(status & TR_STATUS_DOWNLOAD) {
    727     if(0 > eta)
    728       top = g_strdup_printf(_("Stalled (%.1f%%)"), prog);
    729     else {
    730       timestr = readabletime(eta);
    731       top = g_strdup_printf(_("Finishing in %s (%.1f%%)"), timestr, prog);
    732       g_free(timestr);
    733     }
    734   }
    735   else if(status & TR_STATUS_SEED)
    736     top = g_strdup_printf(ngettext("Seeding, uploading to %d of %d peer",
    737                                    "Seeding, uploading to %d of %d peers",
    738                                    tpeers), dpeers, tpeers);
    739   else if(status & TR_STATUS_STOPPING)
    740     top = g_strdup(_("Stopping..."));
    741   else if(status & TR_STATUS_PAUSE)
    742     top = g_strdup_printf(_("Stopped (%.1f%%)"), prog);
    743   else {
    744     top = g_strdup("");
    745     g_assert_not_reached();
    746   }
    747 
    748   if(TR_OK != err) {
    749     gtk_tree_model_get(model, iter, MC_TERR, &terr, -1);
    750     bottom = g_strconcat(_("Error: "), terr, NULL);
    751     g_free(terr);
    752   }
    753   else if(status & TR_STATUS_DOWNLOAD)
    754     bottom = g_strdup_printf(ngettext("Downloading from %i of %i peer",
    755                                       "Downloading from %i of %i peers",
    756                                       tpeers), upeers, tpeers);
    757   else
    758     bottom = NULL;
    759 
    760   str = g_markup_printf_escaped("<big>%s (%s)</big>\n<small>%s\n%s</small>",
    761                                 name, mb, top, (NULL == bottom ? "" : bottom));
    762   g_object_set(rend, "markup", str, NULL);
    763   g_free(name);
    764   g_free(mb);
    765   g_free(str);
    766   g_free(top);
    767   if(NULL != bottom)
    768     g_free(bottom);
    769 }
    770 
    771 void
    772 dfprog(GtkTreeViewColumn *col SHUTUP, GtkCellRenderer *rend,
    773        GtkTreeModel *model, GtkTreeIter *iter, gpointer gdata SHUTUP) {
    774   char *dlstr, *ulstr, *str, *marked;
    775   gfloat prog, dl, ul;
    776   guint64 down, up;
    777 
    778   gtk_tree_model_get(model, iter, MC_PROG, &prog, MC_DRATE, &dl, MC_URATE, &ul,
    779                      MC_DOWN, &down, MC_UP, &up, -1);
    780   if(0.0 > prog)
    781     prog = 0.0;
    782   else if(1.0 < prog)
    783     prog = 1.0;
    784 
    785   ulstr = readablesize(ul * 1024.0);
    786   if(1.0 == prog) {
    787     dlstr = ratiostr(down, up);
    788     str = g_strdup_printf(_("Ratio: %s\nUL: %s/s"), dlstr, ulstr);
    789   } else {
    790     dlstr = readablesize(dl * 1024.0);
    791     str = g_strdup_printf(_("DL: %s/s\nUL: %s/s"), dlstr, ulstr);
    792   }
    793   marked = g_markup_printf_escaped("<small>%s</small>", str);
    794   g_object_set(rend, "markup", str, "progress", prog, NULL);
    795   g_free(dlstr);
    796   g_free(ulstr);
    797   g_free(str);
    798   g_free(marked);
    799531}
    800532
     
    807539  GtkTreeIter iter;
    808540  float up, down;
    809   char *upstr, *downstr, *str;
    810541
    811542  if(0 < global_sigcount) {
     
    831562  }
    832563
    833   /* update the status bar */
    834   tr_torrentRates(tr_backend_handle(data->back), &up, &down);
    835   downstr = readablesize(down * 1024.0);
    836   upstr = readablesize(up * 1024.0);
    837   str = g_strdup_printf(_("     Total DL: %s/s     Total UL: %s/s"),
    838                         upstr, downstr);
    839   gtk_statusbar_pop(data->bar, 0);
    840   gtk_statusbar_push(data->bar, 0, str);
    841   g_free(str);
    842   g_free(upstr);
    843   g_free(downstr);
    844 
    845   /* the status of the selected item may have changed, so update the buttons */
    846   fixbuttons(NULL, data);
     564  /* update the main window's statusbar and toolbar buttons */
     565  tr_torrentRates( tr_backend_handle( data->back ), &down, &up );
     566  tr_window_update( TR_WINDOW(data->wind), down, up );
    847567
    848568  /* check for politely stopped torrents unless we're exiting */
     
    856576}
    857577
    858 /* show a popup menu for a right-click on the list */
    859 gboolean
    860 listclick(GtkWidget *widget SHUTUP, GdkEventButton *event, gpointer gdata) {
    861   struct cbdata *data = gdata;
    862   GtkTreeSelection *sel = gtk_tree_view_get_selection(data->view);
    863   GtkTreePath *path;
    864   GtkTreeIter iter;
    865   int status;
    866   TrTorrent *tor, *issel;
    867 
    868   if(GDK_BUTTON_PRESS == event->type && 3 == event->button) {
    869     /* find what row, if any, the user clicked on */
    870     if(!gtk_tree_view_get_path_at_pos(data->view, event->x, event->y, &path,
    871                                       NULL, NULL, NULL))
    872       gtk_tree_selection_unselect_all(sel);
    873     else {
    874       if(gtk_tree_model_get_iter(data->model, &iter, path)) {
    875         /* get torrent and status for the right-clicked row */
    876         gtk_tree_model_get(data->model, &iter, MC_TORRENT, &tor,
    877                            MC_STAT, &status, -1);
    878         issel = tor;
    879         gtk_tree_selection_selected_foreach(sel, istorsel, &issel);
    880         g_object_unref(tor);
    881         /* if the clicked row isn't selected, select only it */
    882         if(NULL != issel) {
    883           gtk_tree_selection_unselect_all(sel);
    884           gtk_tree_selection_select_iter(sel, &iter);
    885         }
    886       }
    887       gtk_tree_path_free(path);
    888     }
    889     dopopupmenu(event, data);
    890     return TRUE;
    891   }
    892 
    893   return FALSE;
    894 }
    895 
    896 gboolean
    897 listpopup(GtkWidget *widget SHUTUP, gpointer gdata) {
    898   dopopupmenu(NULL, gdata);
    899   return TRUE;
    900 }
    901 
    902 void
    903 dopopupmenu(GdkEventButton *event, struct cbdata *data) {
    904   GtkTreeSelection *sel = gtk_tree_view_get_selection(data->view);
    905   int count = gtk_tree_selection_count_selected_rows(sel);
    906   GtkWidget *menu = gtk_menu_new();
    907   GtkWidget *item;
    908   unsigned int ii;
    909   int status = 0;
    910 
    911   if(NULL != data->stupidpopuphack)
    912     gtk_widget_destroy(data->stupidpopuphack);
    913   data->stupidpopuphack = menu;
    914 
    915   status = 0;
    916   gtk_tree_selection_selected_foreach(sel, orstatus, &status);
    917 
    918   for(ii = 0; ii < ALEN(actionitems); ii++) {
    919     if(actionitems[ii].nomenu ||
    920        (actionitems[ii].avail &&
    921         (0 == count || !(actionitems[ii].avail & status))))
    922       continue;
    923     item = gtk_menu_item_new_with_label(gettext(actionitems[ii].name));
    924     /* set the action for the menu item */
    925     g_object_set_data(G_OBJECT(item), LIST_ACTION,
    926                       GINT_TO_POINTER(actionitems[ii].act));
    927     g_signal_connect(G_OBJECT(item), "activate",
    928                      G_CALLBACK(actionclick), data);
    929     gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
    930   }
    931 
    932   gtk_widget_show_all(menu);
    933 
    934   gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
    935                  (NULL == event ? 0 : event->button),
    936                  gdk_event_get_time((GdkEvent*)event));
    937 }
    938 
    939 void
     578static void
    940579boolwindclosed(GtkWidget *widget SHUTUP, gpointer gdata) {
    941580  gboolean *preachy_gcc = gdata;
     
    944583}
    945584
    946 void
    947 actionclick(GtkWidget *widget, gpointer gdata) {
    948   struct cbdata *data = gdata;
    949   enum listact act;
     585static void
     586windact( GtkWidget * wind SHUTUP, int action, gpointer gdata )
     587{
     588    g_assert( 0 <= action );
     589    handleaction( gdata, action );
     590}
     591
     592static void
     593handleaction( struct cbdata * data, enum action act )
     594{
    950595  GtkTreeSelection *sel;
    951596  GList *rows, *ii;
     
    954599  GtkTreeIter iter;
    955600  TrTorrent *tor;
    956   unsigned int actoff, status;
     601  int status;
    957602  gboolean changed;
    958603  GtkWidget * win;
    959604
    960   act = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), LIST_ACTION));
    961 
    962   switch(act) {
    963     case ACT_OPEN:
    964       makeaddwind(data->wind, addtorrents, data);
    965       return;
    966     case ACT_PREF:
    967       if( !data->prefsopen ) {
    968         data->prefsopen = TRUE;
    969         win = makeprefwindow( data->wind, data->back );
    970         g_signal_connect( win, "destroy", G_CALLBACK( boolwindclosed ),
    971                           &data->prefsopen );
    972       }
    973       return;
    974     case ACT_DEBUG:
    975       if( !data->msgwinopen ) {
    976         data->msgwinopen = TRUE;
    977         win = msgwin_create();
    978         g_signal_connect( win, "destroy", G_CALLBACK( boolwindclosed ),
    979                           &data->msgwinopen );
    980       }
    981       return;
    982     case ACT_START:
    983     case ACT_STOP:
    984     case ACT_DELETE:
    985     case ACT_INFO:
    986       break;
    987   }
    988 
    989   sel = gtk_tree_view_get_selection(data->view);
    990   rows = gtk_tree_selection_get_selected_rows(sel, NULL);
    991 
     605  g_assert( ACTION_COUNT > act );
     606
     607  switch( act )
     608  {
     609      case ACT_OPEN:
     610          makeaddwind( data->wind, addtorrents, data );
     611          return;
     612      case ACT_PREF:
     613          if( !data->prefsopen )
     614          {
     615              data->prefsopen = TRUE;
     616              win = makeprefwindow( data->wind, data->back );
     617              g_signal_connect( win, "destroy", G_CALLBACK( boolwindclosed ),
     618                                &data->prefsopen );
     619          }
     620          return;
     621      case ACT_DEBUG:
     622          if( !data->msgwinopen )
     623          {
     624              data->msgwinopen = TRUE;
     625              win = msgwin_create();
     626              g_signal_connect( win, "destroy", G_CALLBACK( boolwindclosed ),
     627                                &data->msgwinopen );
     628          }
     629          return;
     630      case ACT_START:
     631      case ACT_STOP:
     632      case ACT_DELETE:
     633      case ACT_INFO:
     634      case ACTION_COUNT:
     635          break;
     636  }
     637
     638  /* get a list of references to selected rows */
     639  g_object_get( data->wind, "selection", &sel, NULL );
     640  rows = gtk_tree_selection_get_selected_rows( sel, NULL );
    992641  for(ii = rows; NULL != ii; ii = ii->next) {
    993642    ref = gtk_tree_row_reference_new(data->model, ii->data);
     
    995644    ii->data = ref;
    996645  }
    997 
    998   for(actoff = 0; actoff < ALEN(actionitems); actoff++)
    999     if(actionitems[actoff].act == act)
    1000       break;
    1001   g_assert(actoff < ALEN(actionitems));
    1002646
    1003647  changed = FALSE;
     
    1007651      gtk_tree_model_get(data->model, &iter, MC_TORRENT, &tor,
    1008652                         MC_STAT, &status, -1);
    1009       /* check if this action is valid for this torrent */
    1010       if((!actionitems[actoff].avail || actionitems[actoff].avail & status) &&
    1011          !actionitems[actoff].nomenu) {
    1012         switch(act) {
    1013           case ACT_START:
    1014             tr_torrentStart(tr_torrent_handle(tor));
    1015             changed = TRUE;
    1016             break;
    1017           case ACT_STOP:
    1018             tr_torrentStop(tr_torrent_handle(tor));
    1019             changed = TRUE;
    1020             break;
    1021           case ACT_DELETE:
    1022             /* tor will be unref'd in the politely_stopped signal handler */
    1023             g_object_ref(tor);
    1024             tr_torrent_stop_politely(tor);
    1025             if(TR_FLAG_SAVE & tr_torrent_info(tor)->flags)
    1026               tr_torrentRemoveSaved(tr_torrent_handle(tor));
    1027             gtk_list_store_remove(GTK_LIST_STORE(data->model), &iter);
    1028             changed = TRUE;
    1029             break;
    1030           case ACT_INFO:
    1031             makeinfowind(data->wind, tor);
    1032             break;
    1033           case ACT_OPEN:
    1034           case ACT_PREF:
    1035           case ACT_DEBUG:
    1036             break;
    1037         }
     653      if( ACT_ISAVAIL( actions[act].flags, status ) )
     654
     655      {
     656          switch( act )
     657          {
     658              case ACT_START:
     659                  tr_torrentStart( tr_torrent_handle( tor ) );
     660                  changed = TRUE;
     661                  break;
     662              case ACT_STOP:
     663                  tr_torrentStop( tr_torrent_handle( tor ) );
     664                  changed = TRUE;
     665                  break;
     666              case ACT_DELETE:
     667                  /* tor will be unref'd in the politely_stopped handler */
     668                  g_object_ref( tor );
     669                  tr_torrent_stop_politely( tor );
     670                  if( TR_FLAG_SAVE & tr_torrent_info( tor )->flags )
     671                  {
     672                      tr_torrentRemoveSaved( tr_torrent_handle( tor ) );
     673                  }
     674                  gtk_list_store_remove( GTK_LIST_STORE( data->model ),
     675                                         &iter );
     676                  changed = TRUE;
     677                  break;
     678              case ACT_INFO:
     679                  makeinfowind( data->wind, tor );
     680                  break;
     681              case ACT_OPEN:
     682              case ACT_PREF:
     683              case ACT_DEBUG:
     684              case ACTION_COUNT:
     685                  break;
     686          }
    1038687      }
    1039688      g_object_unref(tor);
     
    1048697    savetorrents(data);
    1049698    updatemodel(data);
    1050   }
    1051 }
    1052 
    1053 gint
    1054 intrevcmp(gconstpointer a, gconstpointer b) {
    1055   int aint = GPOINTER_TO_INT(a);
    1056   int bint = GPOINTER_TO_INT(b);
    1057 
    1058   if(bint > aint)
    1059     return 1;
    1060   else if(bint < aint)
    1061     return -1;
    1062   else
    1063     return 0;
    1064 }
    1065 
    1066 void
    1067 doubleclick(GtkWidget *widget SHUTUP, GtkTreePath *path,
    1068             GtkTreeViewColumn *col SHUTUP, gpointer gdata) {
    1069   struct cbdata *data = gdata;
    1070   GtkTreeIter iter;
    1071   TrTorrent *tor;
    1072 
    1073   if(gtk_tree_model_get_iter(data->model, &iter, path)) {
    1074     gtk_tree_model_get(data->model, &iter, MC_TORRENT, &tor, -1);
    1075     makeinfowind(data->wind, tor);
    1076     g_object_unref(tor);
    1077699  }
    1078700}
     
    1101723}
    1102724
    1103 void
     725static void
    1104726addtorrents(void *vdata, void *state, GList *files,
    1105727            const char *dir, guint flags) {
     
    1166788}
    1167789
    1168 void
    1169 savetorrents(struct cbdata *data) {
    1170   char *errstr;
    1171 
    1172   tr_backend_save_state(data->back, &errstr);
    1173   if(NULL != errstr) {
    1174     errmsg(data->wind, "%s", errstr);
    1175     g_free(errstr);
    1176   }
    1177 }
    1178 
    1179 /* use with gtk_tree_selection_selected_foreach to | status of selected rows */
    1180 void
    1181 orstatus(GtkTreeModel *model, GtkTreePath *path SHUTUP, GtkTreeIter *iter,
    1182          gpointer gdata) {
    1183   int *allstatus = gdata;
    1184   int status;
    1185 
    1186   gtk_tree_model_get(model, iter, MC_STAT, &status, -1);
    1187   *allstatus |= status;
    1188 }
    1189 
    1190 /* data should be a TrTorrent**, will set torrent to NULL if it's selected */
    1191 void
    1192 istorsel(GtkTreeModel *model, GtkTreePath *path SHUTUP, GtkTreeIter *iter,
    1193          gpointer gdata) {
    1194   TrTorrent **torref = gdata;
    1195   TrTorrent *tor;
    1196 
    1197   if(NULL != *torref) {
    1198     gtk_tree_model_get(model, iter, MC_TORRENT, &tor, -1);
    1199     if(tor == *torref)
    1200       *torref = NULL;
    1201     g_object_unref(tor);
    1202   }
    1203 }
    1204 
    1205 void
     790static void
     791savetorrents( struct cbdata *data )
     792{
     793    char * errstr;
     794
     795    tr_backend_save_state( data->back, &errstr );
     796    if( NULL != errstr )
     797    {
     798        errmsg( data->wind, "%s", errstr );
     799        g_free( errstr );
     800    }
     801}
     802
     803static void
    1206804safepipe(void) {
    1207805  struct sigaction sa;
     
    1212810}
    1213811
    1214 void
     812static void
    1215813setupsighandlers(void) {
    1216814  int sigs[] = {SIGHUP, SIGINT, SIGQUIT, SIGTERM, SIGUSR1, SIGUSR2};
     
    1224822}
    1225823
    1226 void
     824static void
    1227825fatalsig(int sig) {
    1228826  struct sigaction sa;
  • trunk/gtk/tr_cell_renderer_progress.c

    r1473 r1475  
    22 * $Id$
    33 *
    4  * Copyright (c) 2006 Transmission authors and contributors
     4 * Copyright (c) 2006-2007 Transmission authors and contributors
    55 *
    66 * Permission is hereby granted, free of charge, to any person obtaining a
     
    7878    };
    7979    type = g_type_register_static(GTK_TYPE_CELL_RENDERER,
    80                                   "TrCellRendererProgressType", &info, 0);
     80                                  "TrCellRendererProgress", &info, 0);
    8181  }
    8282  return type;
  • trunk/gtk/tr_cell_renderer_progress.h

    r1473 r1475  
    22 * $Id$
    33 *
    4  * Copyright (c) 2006 Transmission authors and contributors
     4 * Copyright (c) 2006-2007 Transmission authors and contributors
    55 *
    66 * Permission is hereby granted, free of charge, to any person obtaining a
  • trunk/gtk/tr_torrent.c

    r1440 r1475  
    22 * $Id$
    33 *
    4  * Copyright (c) 2006 Transmission authors and contributors
     4 * Copyright (c) 2006-2007 Transmission authors and contributors
    55 *
    66 * Permission is hereby granted, free of charge, to any person obtaining a
     
    7979      NULL,
    8080    };
    81     type = g_type_register_static(G_TYPE_OBJECT, "TrTorrentType", &info, 0);
     81    type = g_type_register_static(G_TYPE_OBJECT, "TrTorrent", &info, 0);
    8282  }
    8383  return type;
  • trunk/gtk/util.h

    r1468 r1475  
    22 * $Id$
    33 *
    4  * Copyright (c) 2005-2006 Transmission authors and contributors
     4 * Copyright (c) 2005-2007 Transmission authors and contributors
    55 *
    66 * Permission is hereby granted, free of charge, to any person obtaining a
  • trunk/mk/gtk.mk

    r1470 r1475  
    55
    66SRCS = conf.c dialogs.c io.c ipc.c main.c msgwin.c tr_backend.c tr_torrent.c \
    7         tr_cell_renderer_progress.c util.c
     7        tr_cell_renderer_progress.c tr_window.c util.c
    88OBJS = $(SRCS:%.c=%.o)
    99
Note: See TracChangeset for help on using the changeset viewer.