Changeset 269


Ignore:
Timestamp:
May 31, 2006, 11:20:59 PM (17 years ago)
Author:
joshe
Message:

Wait and try to send a stopped event when removing a torrent.

Location:
trunk/gtk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/gtk/main.c

    r261 r269  
    6868  gboolean prefsopen;
    6969  GtkWidget *stupidpopuphack;
     70  gboolean closing;
    7071};
    7172
     
    117118void
    118119actionclick(GtkWidget *widget, gpointer gdata);
    119 void
    120 popupaction(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter,
    121             gpointer gdata);
    122120gint
    123121intrevcmp(gconstpointer a, gconstpointer b);
     
    302300  data->prefsopen = FALSE;
    303301  data->stupidpopuphack = NULL;
     302  data->closing = FALSE;
    304303
    305304  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_NEVER,
     
    460459  struct exitdata *edata;
    461460  unsigned int ii;
     461  GtkTreeIter iter;
     462  TrTorrent *tor;
     463
     464  data->closing = TRUE;
    462465
    463466  /* stop the update timer */
     
    466469  data->timer = 0;
    467470
    468   /* try to stop all the torrents */
     471  /*
     472    Add a reference to all torrents in the list, which will be removed
     473    when the politely-stopped signal is emitted.  This is necessary
     474    because actionclick() adds a reference when it removes a torrent
     475    from the model and calls tr_torrent_stop_polite() on it.
     476  */
     477  if(gtk_tree_model_get_iter_first(data->model, &iter)) {
     478    do
     479      gtk_tree_model_get(data->model, &iter, MC_TORRENT, &tor, -1);
     480    while(gtk_tree_model_iter_next(data->model, &iter));
     481  }
     482
     483  /* try to politely stop all the torrents */
    469484  tr_backend_stop_torrents(data->back);
    470485
     
    773788  fixbuttons(NULL, data);
    774789
     790  /* check for politely stopped torrents unless we're exiting */
     791  if(!data->closing)
     792    tr_backend_torrents_stopped(data->back);
     793
    775794  return TRUE;
    776795}
     
    857876}
    858877
    859 struct actioninfo {
    860   GtkWindow *wind;
    861   enum listact act;
    862   unsigned int off;
    863   GtkTreeSelection *sel;
    864   TrBackend *back;
    865   gboolean changed;
    866   GList *dead;
    867 };
    868 
    869878void
    870879actionclick(GtkWidget *widget, gpointer gdata) {
    871880  struct cbdata *data = gdata;
    872   struct actioninfo info = {
    873     data->wind,
    874     GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), LIST_ACTION)),
    875     0,
    876     gtk_tree_view_get_selection(data->view),
    877     data->back,
    878     FALSE,
    879     NULL,
    880   };
    881   GtkTreeSelection *sel = gtk_tree_view_get_selection(data->view);
    882   GList *ii;
     881  enum listact act;
     882  GtkTreeSelection *sel;
     883  GList *rows, *ii;
     884  GtkTreeRowReference *ref;
    883885  GtkTreePath *path;
    884886  GtkTreeIter iter;
    885 
    886   switch(info.act) {
     887  TrTorrent *tor;
     888  unsigned int actoff, status;
     889  gboolean changed;
     890
     891  act = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), LIST_ACTION));
     892
     893  switch(act) {
    887894    case ACT_OPEN:
    888895      makeaddwind(data->wind, addtorrents, data);
     
    899906  }
    900907
    901   for(info.off = 0; info.off < ALEN(actionitems); info.off++)
    902     if(actionitems[info.off].act == info.act)
     908  sel = gtk_tree_view_get_selection(data->view);
     909  rows = gtk_tree_selection_get_selected_rows(sel, NULL);
     910
     911  for(ii = rows; NULL != ii; ii = ii->next) {
     912    ref = gtk_tree_row_reference_new(data->model, ii->data);
     913    gtk_tree_path_free(ii->data);
     914    ii->data = ref;
     915  }
     916
     917  for(actoff = 0; actoff < ALEN(actionitems); actoff++)
     918    if(actionitems[actoff].act == act)
    903919      break;
    904   g_assert(info.off < ALEN(actionitems));
    905 
    906   gtk_tree_selection_selected_foreach(sel, popupaction, &info);
    907 
    908   for(ii = info.dead; NULL != ii; ii = ii->next) {
    909     g_assert(gtk_tree_row_reference_valid(ii->data));
    910     path = gtk_tree_row_reference_get_path(ii->data);
    911     gtk_tree_selection_unselect_path(info.sel, path);
    912     if(gtk_tree_model_get_iter(data->model, &iter, path))
    913        gtk_list_store_remove(GTK_LIST_STORE(data->model), &iter);
    914     else {
    915       g_assert_not_reached();
     920  g_assert(actoff < ALEN(actionitems));
     921
     922  changed = FALSE;
     923  for(ii = rows; NULL != ii; ii = ii->next) {
     924    if(NULL != (path = gtk_tree_row_reference_get_path(ii->data)) &&
     925       gtk_tree_model_get_iter(data->model, &iter, path)) {
     926      gtk_tree_model_get(data->model, &iter, MC_TORRENT, &tor,
     927                         MC_STAT, &status, -1);
     928      /* check if this action is valid for this torrent */
     929      if((!actionitems[actoff].avail || actionitems[actoff].avail & status) &&
     930         !actionitems[actoff].nomenu) {
     931        switch(act) {
     932          case ACT_START:
     933            tr_torrentStart(tr_torrent_handle(tor));
     934            changed = TRUE;
     935            break;
     936          case ACT_STOP:
     937            tr_torrentStop(tr_torrent_handle(tor));
     938            changed = TRUE;
     939            break;
     940          case ACT_DELETE:
     941            /* tor will be unref'd in the politely_stopped signal handler */
     942            g_object_ref(tor);
     943            tr_torrent_stop_politely(tor);
     944            gtk_list_store_remove(GTK_LIST_STORE(data->model), &iter);
     945            changed = TRUE;
     946            break;
     947          case ACT_INFO:
     948            makeinfowind(data->wind, tor);
     949            break;
     950          case ACT_OPEN:
     951          case ACT_PREF:
     952            break;
     953        }
     954      }
     955      g_object_unref(tor);
    916956    }
    917     gtk_tree_path_free(path);
     957    if(NULL != path)
     958      gtk_tree_path_free(path);
    918959    gtk_tree_row_reference_free(ii->data);
    919960  }
    920   g_list_free(info.dead);
    921 
    922   if(info.changed) {
     961  g_list_free(rows);
     962
     963  if(changed) {
    923964    savetorrents(data);
    924965    updatemodel(data);
    925966  }
    926 }
    927 
    928 void
    929 popupaction(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter,
    930             gpointer gdata) {
    931   struct actioninfo *in = gdata;
    932   TrTorrent *tor;
    933   int status;
    934 
    935   gtk_tree_model_get(model, iter, MC_TORRENT, &tor, MC_STAT, &status, -1);
    936 
    937   /* check if this action is valid for this torrent */
    938   if((!actionitems[in->off].avail || actionitems[in->off].avail & status) &&
    939      !actionitems[in->off].nomenu) {
    940     switch(in->act) {
    941       case ACT_START:
    942         tr_torrentStart(tr_torrent_handle(tor));
    943         in->changed = TRUE;
    944         break;
    945       case ACT_STOP:
    946         tr_torrentStop(tr_torrent_handle(tor));
    947         in->changed = TRUE;
    948         break;
    949       case ACT_DELETE:
    950         in->dead = g_list_append(in->dead,
    951                                  gtk_tree_row_reference_new(model, path));
    952         in->changed = TRUE;
    953         break;
    954       case ACT_INFO:
    955         makeinfowind(in->wind, tor);
    956         break;
    957       case ACT_OPEN:
    958       case ACT_PREF:
    959         break;
    960     }
    961   }
    962 
    963   g_object_unref(tor);
    964967}
    965968
     
    10351038    gtk_list_store_set(GTK_LIST_STORE(data->model), &iter,
    10361039                       MC_TORRENT, ii->data, -1);
     1040    /* we will always ref a torrent before politely stopping it */
     1041    g_signal_connect(ii->data, "politely_stopped",
     1042                     G_CALLBACK(g_object_unref), data);
    10371043    g_object_unref(ii->data);
    10381044  }
  • trunk/gtk/tr_backend.c

    r261 r269  
    202202tr_backend_save_state(TrBackend *back, char **errstr) {
    203203  benc_val_t state;
    204   int ii;
    205   GList *jj;
     204  GList *ii;
    206205
    207206  TR_IS_BACKEND(back);
     
    209208  bzero(&state, sizeof(state));
    210209  state.type = TYPE_LIST;
    211   state.val.l.alloc = state.val.l.count = g_list_length(back->torrents);
     210  state.val.l.alloc = g_list_length(back->torrents);
    212211  state.val.l.vals = g_new0(benc_val_t, state.val.l.alloc);
    213212
    214   for(ii = 0, jj = back->torrents; NULL != jj; ii++, jj = jj->next)
    215     tr_torrent_get_state(jj->data, state.val.l.vals + ii);
     213  for(ii = back->torrents; NULL != ii; ii = ii->next) {
     214    tr_torrent_get_state(ii->data, state.val.l.vals + state.val.l.count);
     215    if(0 != state.val.l.vals[state.val.l.count].type)
     216      state.val.l.count++;
     217  }
    216218
    217219  cf_savestate(&state, errstr);
     
    269271
    270272  for(ii = back->torrents; NULL != ii; ii = ii->next)
    271     if(TR_STATUS_ACTIVE & tr_torrent_stat(ii->data)->status)
    272       tr_torrentStop(tr_torrent_handle(ii->data));
     273    tr_torrent_stop_politely(ii->data);
    273274}
    274275
    275276gboolean
    276277tr_backend_torrents_stopped(TrBackend *back) {
    277   GList *ii;
    278 
    279   TR_IS_BACKEND(back);
    280 
    281   for(ii = back->torrents; NULL != ii; ii = ii->next)
    282     if(TR_STATUS_ACTIVE & tr_torrent_stat(ii->data)->status)
    283       return FALSE;
    284 
    285   return TRUE;
    286 }
     278  GList *ii, *list;
     279  gboolean ret = TRUE;
     280
     281  TR_IS_BACKEND(back);
     282
     283  list = g_list_copy(back->torrents);
     284  for(ii = list; NULL != ii; ii = ii->next)
     285    if(!(TR_STATUS_PAUSE & tr_torrent_stat_polite(ii->data)->status))
     286      ret = FALSE;
     287  g_list_free(list);
     288
     289  return ret;
     290}
  • trunk/gtk/tr_torrent.c

    r261 r269  
    9191tr_torrent_class_init(gpointer g_class, gpointer g_class_data SHUTUP) {
    9292  GObjectClass *gobject_class = G_OBJECT_CLASS(g_class);
    93   //TrTorrentClass *klass = TR_TORRENT_CLASS(g_class);
     93  TrTorrentClass *klass = TR_TORRENT_CLASS(g_class);
    9494  GParamSpec *pspec;
    9595
     
    118118                               G_PARAM_READWRITE);
    119119  g_object_class_install_property(gobject_class, TR_TORRENT_PAUSED, pspec);
     120
     121  klass->paused_signal_id = g_signal_newv("politely-stopped",
     122                                          G_TYPE_FROM_CLASS(g_class),
     123                                          G_SIGNAL_RUN_LAST, NULL, NULL, NULL,
     124                                          g_cclosure_marshal_VOID__VOID,
     125                                          G_TYPE_NONE, 0, NULL);
    120126}
    121127
     
    127133  self->back = NULL;
    128134  self->dir = NULL;
     135  self->closing = FALSE;
    129136  self->disposed = FALSE;
    130137}
     
    341348    return;
    342349
     350  if(tor->closing)
     351    return;
     352
    343353  state->type = TYPE_DICT;
    344354  state->val.l.vals = g_new0(benc_val_t, len);
     
    379389  return (TR_STATUS_INACTIVE & st->status ? TRUE : FALSE);
    380390}
     391
     392void
     393tr_torrent_stop_politely(TrTorrent *tor) {
     394  tr_stat_t *st;
     395
     396  TR_IS_TORRENT(tor);
     397
     398  if(tor->disposed)
     399    return;
     400
     401  if(!tor->closing) {
     402    st = tr_torrent_stat(tor);
     403    tor->closing = TRUE;
     404    if(TR_STATUS_ACTIVE & st->status)
     405      tr_torrentStop(tor->handle);
     406  }
     407}
     408
     409tr_stat_t *
     410tr_torrent_stat_polite(TrTorrent *tor) {
     411  TrTorrentClass *klass;
     412  tr_stat_t *st = tr_torrentStat(tor->handle);
     413
     414  if(tor->disposed)
     415    return st;
     416
     417  if(tor->closing && TR_STATUS_PAUSE & st->status) {
     418    tor->closing = FALSE;
     419    klass = g_type_class_peek(TR_TORRENT_TYPE);
     420    g_signal_emit(tor, klass->paused_signal_id, 0, NULL);
     421  }
     422
     423  return st;
     424}
  • trunk/gtk/tr_torrent.h

    r261 r269  
    5656  GObject *back;
    5757  char *dir;
     58  gboolean closing;
    5859  gboolean disposed;
    5960};
     
    6162struct _TrTorrentClass {
    6263  GObjectClass parent;
     64  int paused_signal_id;
    6365};
    6466
     
    8284tr_torrent_new_with_state(GObject *backend, benc_val_t *state, char **err);
    8385
     86void
     87tr_torrent_stop_politely(TrTorrent *tor);
     88
     89tr_stat_t *
     90tr_torrent_stat_polite(TrTorrent *tor);
     91
    8492#ifdef TR_WANT_TORRENT_PRIVATE
    8593void
Note: See TracChangeset for help on using the changeset viewer.