Changeset 161
- Timestamp:
- Mar 20, 2006, 7:35:36 PM (16 years ago)
- Location:
- branches/new_api/gtk
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/new_api/gtk/conf.c
r91 r161 415 415 416 416 gboolean 417 cf_savestate( int count, tr_stat_t *torrents, char **errstr) {417 cf_savestate(GList *torrents, char **errstr) { 418 418 char *file = g_build_filename(confdir, FILE_STATE, NULL); 419 419 char *tmpfile = g_build_filename(confdir, FILE_STATE_TMP, NULL); 420 420 GIOChannel *io = NULL; 421 421 GError *err; 422 int fd , ii;422 int fd; 423 423 char *torrentfile, *torrentdir, *line; 424 424 gsize written; 425 425 gboolean paused; 426 426 GIOStatus res; 427 tr_stat_t *sb; 428 tr_info_t *in; 427 429 428 430 *errstr = NULL; … … 445 447 446 448 err = NULL; 447 for(ii = 0; ii < count; ii++) { 448 /* XXX need a better way to query running/stopped state */ 449 paused = ((TR_STATUS_STOPPING | TR_STATUS_PAUSE) & torrents[ii].status); 450 torrentfile = g_strescape(torrents[ii].info.torrent, ""); 451 torrentdir = g_strescape(torrents[ii].folder, ""); 449 while(NULL != torrents) { 450 sb = tr_torrentStat(torrents->data); 451 in = tr_torrentInfo(torrents->data); 452 paused = (TR_STATUS_INACTIVE & sb->status); 453 torrentfile = g_strescape(in->torrent, ""); 454 torrentdir = g_strescape(tr_torrentGetFolder(torrents->data), ""); 452 455 /* g_strcompress */ 453 456 line = g_strdup_printf("torrent=\"%s\" dir=\"%s\" paused=\"%s\"%c", … … 467 470 goto done; 468 471 } 472 torrents = torrents->next; 469 473 } 470 474 if(NULL != err || -
branches/new_api/gtk/conf.h
r51 r161 51 51 cf_loadstate(char **errstr); 52 52 gboolean 53 cf_savestate( int count, tr_stat_t *torrents, char **errstr);53 cf_savestate(GList *torrents, char **errstr); 54 54 void 55 55 cf_freestate(struct cf_torrentstate *state); -
branches/new_api/gtk/dialogs.c
r131 r161 50 50 add_torrent_func_t addfunc; 51 51 GtkWindow *parent; 52 tr_handle_t *tr;53 52 torrents_added_func_t donefunc; 54 void *d onedata;53 void *data; 55 54 gboolean autostart; 56 55 gboolean usingaltdir; … … 220 219 } 221 220 221 /* XXX would be nice to have errno strings, are they printed to stdout? */ 222 222 tr_setBindPort(data->tr, gtk_spin_button_get_value_as_int(data->port)); 223 223 setlimit(data->tr); … … 241 241 242 242 void 243 makeaddwind( add_torrent_func_t addfunc, GtkWindow *parent, tr_handle_t *tr,244 torrents_added_func_t donefunc, void * donedata) {243 makeaddwind(GtkWindow *parent, add_torrent_func_t addfunc, 244 torrents_added_func_t donefunc, void *cbdata) { 245 245 GtkWidget *wind = gtk_file_chooser_dialog_new(_("Add a Torrent"), parent, 246 246 GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, … … 261 261 data->addfunc = addfunc; 262 262 data->parent = parent; 263 data->tr = tr;264 263 data->donefunc = donefunc; 265 data->d onedata = donedata;264 data->data = cbdata; 266 265 data->autostart = TRUE; 267 266 data->usingaltdir = FALSE; … … 327 326 files = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(widget)); 328 327 for(ii = files; NULL != ii; ii = ii->next) 329 if(data->addfunc(data->tr, data->parent, ii->data, dir, 328 if(data->addfunc(data->data, ii->data, dir, 329 /* XXX need to group errors here */ 330 330 !data->autostart, NULL)) 331 331 added = TRUE; 332 332 if(added) 333 data->donefunc(data->d onedata);333 data->donefunc(data->data); 334 334 if(NULL != dir) 335 335 g_free(dir); … … 376 376 377 377 void 378 makeinfowind(GtkWindow *parent, tr_ handle_t *tr, int id) {378 makeinfowind(GtkWindow *parent, tr_torrent_t *tor) { 379 379 tr_stat_t *sb; 380 tr_info_t *in; 380 381 GtkWidget *wind, *label; 381 382 int ii; … … 384 385 GtkWidget *table = gtk_table_new(rowcount, 2, FALSE); 385 386 386 /* XXX would be nice to be able to stat just one */ 387 if(id >= tr_torrentStat(tr, &sb)) 388 assert(!"XXX "); 389 str = g_strdup_printf(_("%s Properties"), sb[id].info.name); 387 sb = tr_torrentStat(tor); 388 in = tr_torrentInfo(tor); 389 str = g_strdup_printf(_("%s Properties"), in->name); 390 390 wind = gtk_dialog_new_with_buttons(str, parent, 391 391 GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR, … … 402 402 label = gtk_label_new(NULL); 403 403 gtk_label_set_selectable(GTK_LABEL(label), TRUE); 404 str = g_markup_printf_escaped("<big>%s</big>", sb[id].info.name);404 str = g_markup_printf_escaped("<big>%s</big>", in->name); 405 405 gtk_label_set_markup(GTK_LABEL(label), str); 406 406 g_free(str); … … 411 411 INFOSEP(table, ii); 412 412 413 if(80 == sb[id].info.trackerPort)413 if(80 == in->trackerPort) 414 414 INFOLINEA(table, ii, _("Tracker:"), g_strdup_printf("http://%s", 415 sb[id].info.trackerAddress));415 in->trackerAddress)); 416 416 else 417 417 INFOLINEA(table, ii, _("Tracker:"), g_strdup_printf("http://%s:%i", 418 sb[id].info.trackerAddress, sb[id].info.trackerPort));419 INFOLINE(table, ii, _("Announce:"), sb[id].info.trackerAnnounce);420 INFOLINEA(table, ii, _("Piece Size:"), readablesize( sb[id].info.pieceSize));421 INFOLINEF(table, ii, "%i", _("Pieces:"), sb[id].info.pieceCount);422 INFOLINEA(table, ii, _("Total Size:"), readablesize( sb[id].info.totalSize));423 if(0 > sb [id].seeders)418 in->trackerAddress, in->trackerPort)); 419 INFOLINE(table, ii, _("Announce:"), in->trackerAnnounce); 420 INFOLINEA(table, ii, _("Piece Size:"), readablesize(in->pieceSize)); 421 INFOLINEF(table, ii, "%i", _("Pieces:"), in->pieceCount); 422 INFOLINEA(table, ii, _("Total Size:"), readablesize(in->totalSize)); 423 if(0 > sb->seeders) 424 424 INFOLINE(table, ii, _("Seeders:"), _("?")); 425 425 else 426 INFOLINEF(table, ii, "%i", _("Seeders:"), sb [id].seeders);427 if(0 > sb [id].leechers)426 INFOLINEF(table, ii, "%i", _("Seeders:"), sb->seeders); 427 if(0 > sb->leechers) 428 428 INFOLINE(table, ii, _("Leechers:"), _("?")); 429 429 else 430 INFOLINEF(table, ii, "%i", _("Leechers:"), sb [id].leechers);430 INFOLINEF(table, ii, "%i", _("Leechers:"), sb->leechers); 431 431 432 432 INFOSEP(table, ii); 433 433 434 INFOLINE(table, ii, _("Directory:"), sb[id].folder);435 INFOLINEA(table, ii, _("Downloaded:"), readablesize(sb [id].downloaded));436 INFOLINEA(table, ii, _("Uploaded:"), readablesize(sb [id].uploaded));434 INFOLINE(table, ii, _("Directory:"), tr_torrentGetFolder(tor)); 435 INFOLINEA(table, ii, _("Downloaded:"), readablesize(sb->downloaded)); 436 INFOLINEA(table, ii, _("Uploaded:"), readablesize(sb->uploaded)); 437 437 438 438 INFOSEP(table, ii); … … 444 444 G_CALLBACK(gtk_widget_destroy), NULL); 445 445 gtk_widget_show_all(wind); 446 free(sb); 447 } 446 } -
branches/new_api/gtk/dialogs.h
r125 r161 38 38 #define DEFAULT_UPLIMIT 20 39 39 40 typedef gboolean (*add_torrent_func_t)( tr_handle_t*, GtkWindow*, const char*, const char *, gboolean, GList **);40 typedef gboolean (*add_torrent_func_t)(void *, const char *, const char *, gboolean, GList **); 41 41 typedef void (*torrents_added_func_t)(void *); 42 42 … … 50 50 /* show the "add a torrent" dialog */ 51 51 void 52 makeaddwind( add_torrent_func_t addfunc, GtkWindow *parent, tr_handle_t *tr,53 torrents_added_func_t donefunc, void * donedata);52 makeaddwind(GtkWindow *parent, add_torrent_func_t addfunc, 53 torrents_added_func_t donefunc, void *cbdata); 54 54 55 55 /* show the info window for a torrent */ 56 56 void 57 makeinfowind(GtkWindow *parent, tr_ handle_t *tr, int index);57 makeinfowind(GtkWindow *parent, tr_torrent_t *tor); 58 58 59 59 #endif /* TG_PREFS_H */ -
branches/new_api/gtk/main.c
r131 r161 28 28 #include <assert.h> 29 29 #include <errno.h> 30 #include <signal.h> 30 31 #include <string.h> 31 32 #include <stdio.h> … … 51 52 tr_handle_t *tr; 52 53 GtkWindow *wind; 53 Gtk ListStore*model;54 GtkTreeModel *model; 54 55 GtkTreeView *view; 55 56 GtkStatusbar *bar; … … 78 79 void 79 80 makewind(GtkWidget *wind, tr_handle_t *tr, GList *saved); 80 gboolean81 winclose(GtkWidget *widget, GdkEvent *event, gpointer gdata);82 gboolean83 exitcheck(gpointer gdata);84 void85 stoptransmission(void *tr);86 void87 setupdrag(GtkWidget *widget, struct cbdata *data);88 void89 gotdrag(GtkWidget *widget, GdkDragContext *dc, gint x, gint y,90 GtkSelectionData *sel, guint info, guint time, gpointer gdata);91 81 GtkWidget * 92 82 makewind_toolbar(struct cbdata *data); 93 83 GtkWidget * 94 84 makewind_list(struct cbdata *data); 85 gboolean 86 winclose(GtkWidget *widget, GdkEvent *event, gpointer gdata); 87 gboolean 88 exitcheck(gpointer gdata); 89 void 90 stoptransmission(tr_handle_t *tr); 91 void 92 setupdrag(GtkWidget *widget, struct cbdata *data); 93 void 94 gotdrag(GtkWidget *widget, GdkDragContext *dc, gint x, gint y, 95 GtkSelectionData *sel, guint info, guint time, gpointer gdata); 95 96 static void 96 97 stylekludge(GObject *obj, GParamSpec *spec, gpointer gdata); … … 114 115 GList *ids, int status); 115 116 void 116 killmenu(GtkWidget *menu, gpointer *gdata SHUTUP);117 killmenu(GtkWidget *menu, gpointer *gdata); 117 118 void 118 119 actionclick(GtkWidget *widget, gpointer gdata); 120 void 121 findtorrent(GtkTreeModel *model, tr_torrent_t *tor, GtkTreeIter *iter); 119 122 gint 120 123 intrevcmp(gconstpointer a, gconstpointer b); … … 124 127 125 128 gboolean 126 addtorrent( tr_handle_t *tr, GtkWindow *parentwind, const char *torrent,127 const char *dir, gboolean paused,GList **errs);129 addtorrent(void *vdata, const char *torrent, const char *dir, gboolean paused, 130 GList **errs); 128 131 void 129 132 addedtorrents(void *vdata); 130 133 gboolean 131 savetorrents(tr_handle_t *tr, GtkWindow *wind , int count, tr_stat_t *stat);134 savetorrents(tr_handle_t *tr, GtkWindow *wind); 132 135 void 133 136 orstatus(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, … … 136 139 makeidlist(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, 137 140 gpointer gdata); 141 void 142 maketorrentlist(tr_torrent_t *tor, void *data); 143 void 144 setupsighandlers(void); 145 void 146 fatalsig(int sig); 138 147 139 148 #define TR_TYPE_PIECES_NAME "tr-type-pieces" … … 147 156 enum listfrom { FROM_BUTTON, FROM_POPUP }; 148 157 149 #define LIST_I NDEX "torrent-list-indexes"158 #define LIST_IDS "torrent-list-ids" 150 159 #define LIST_MENU_WIDGET "torrent-list-popup-menu-widget" 151 160 … … 156 165 N_("Add a new torrent"), "XXX"}, 157 166 {N_("Start"), GTK_STOCK_EXECUTE, ACT_START, FALSE, 158 (TR_STATUS_STOPPING | TR_STATUS_PAUSE),167 TR_STATUS_INACTIVE, 159 168 N_("Start a torrent that is not running"), "XXX"}, 160 169 {N_("Stop"), GTK_STOCK_STOP, ACT_STOP, FALSE, 161 ~(TR_STATUS_STOPPING | TR_STATUS_PAUSE),170 TR_STATUS_ACTIVE, 162 171 N_("Stop a torrent that is running"), "XXX"}, 163 172 {N_("Remove"), GTK_STOCK_REMOVE, ACT_DELETE, FALSE, ~0, … … 170 179 171 180 #define CBDATA_PTR "callback-data-pointer" 181 182 #define SIGCOUNT_MAX 3 183 184 static sig_atomic_t global_sigcount = 0; 185 static int global_lastsig = 0; 186 172 187 int 173 188 main(int argc, char **argv) { … … 179 194 long intval; 180 195 196 setupsighandlers(); 197 181 198 gtk_init(&argc, &argv); 182 199 … … 187 204 188 205 tr = tr_init(); 189 190 setuphandlers(stoptransmission, tr);191 206 192 207 gtk_rc_parse_string( … … 306 321 for(ii = g_list_first(saved); NULL != ii; ii = ii->next) { 307 322 ts = ii->data; 308 addtorrent( tr, GTK_WINDOW(wind), ts->ts_torrent, ts->ts_directory,309 ts->ts_paused,&loaderrs);323 addtorrent(data, ts->ts_torrent, ts->ts_directory, ts->ts_paused, 324 &loaderrs); 310 325 cf_freestate(ts); 311 326 } … … 320 335 g_list_free(loaderrs); 321 336 g_free(str); 322 savetorrents(tr, GTK_WINDOW(wind) , -1, NULL);337 savetorrents(tr, GTK_WINDOW(wind)); 323 338 } 324 339 … … 341 356 } 342 357 343 /* XXX is this the right thing to do? */ 344 #define TR_TORRENT_NEEDS_STOP(t) \ 345 ((t) & TR_STATUS_CHECK || (t) & TR_STATUS_DOWNLOAD || (t) & TR_STATUS_SEED) 358 GtkWidget * 359 makewind_toolbar(struct cbdata *data) { 360 GtkWidget *bar = gtk_toolbar_new(); 361 GtkToolItem *item; 362 unsigned int ii; 363 364 gtk_toolbar_set_tooltips(GTK_TOOLBAR(bar), TRUE); 365 gtk_toolbar_set_show_arrow(GTK_TOOLBAR(bar), FALSE); 366 gtk_toolbar_set_style(GTK_TOOLBAR(bar), GTK_TOOLBAR_BOTH); 367 368 data->buttons = g_new(GtkWidget*, ALEN(actionitems)); 369 370 for(ii = 0; ii < ALEN(actionitems); ii++) { 371 item = gtk_tool_button_new_from_stock(actionitems[ii].id); 372 data->buttons[ii] = GTK_WIDGET(item); 373 gtk_tool_button_set_label(GTK_TOOL_BUTTON(item), 374 gettext(actionitems[ii].name)); 375 gtk_tool_item_set_tooltip(GTK_TOOL_ITEM(item), GTK_TOOLBAR(bar)->tooltips, 376 gettext(actionitems[ii].ttext), 377 actionitems[ii].tpriv); 378 g_object_set_data(G_OBJECT(item), LIST_ACTION, 379 GINT_TO_POINTER(actionitems[ii].act)); 380 g_object_set_data(G_OBJECT(item), LIST_ACTION_FROM, 381 GINT_TO_POINTER(FROM_BUTTON)); 382 g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(actionclick), data); 383 gtk_toolbar_insert(GTK_TOOLBAR(bar), item, -1); 384 } 385 386 return bar; 387 } 388 389 /* XXX check for unused data in model */ 390 enum {MC_NAME, MC_SIZE, MC_STAT, MC_ERR, MC_TERR, MC_PROG, MC_DRATE, MC_URATE, 391 MC_ETA, MC_PEERS, MC_UPEERS, MC_DPEERS, MC_PIECES, MC_DOWN, MC_UP, 392 MC_TORRENT, MC_ROW_COUNT}; 393 394 GtkWidget * 395 makewind_list(struct cbdata *data) { 396 GType types[] = { 397 /* info->name, info->totalSize, status, error, trackerError, */ 398 G_TYPE_STRING, G_TYPE_UINT64, G_TYPE_INT, G_TYPE_INT, G_TYPE_STRING, 399 /* progress, rateDownload, rateUpload, eta, peersTotal, */ 400 G_TYPE_FLOAT, G_TYPE_FLOAT, G_TYPE_FLOAT, G_TYPE_INT, G_TYPE_INT, 401 /* peersUploading, peersDownloading, pieces, downloaded, */ 402 G_TYPE_INT, G_TYPE_INT, TR_TYPE_PIECES, G_TYPE_UINT64, 403 /* uploaded, the handle for the torrent */ 404 G_TYPE_UINT64, G_TYPE_POINTER}; 405 GtkListStore *store; 406 GtkWidget *view; 407 GtkTreeViewColumn *col; 408 GtkTreeSelection *sel; 409 GtkCellRenderer *namerend, *progrend; 410 char *str; 411 412 assert(MC_ROW_COUNT == ALEN(types)); 413 414 store = gtk_list_store_newv(MC_ROW_COUNT, types); 415 view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); 416 /* XXX do I need to worry about reference counts anywhere else? */ 417 g_object_unref(G_OBJECT(store)); 418 data->model = GTK_TREE_MODEL(store); 419 data->view = GTK_TREE_VIEW(view); 420 421 namerend = gtk_cell_renderer_text_new(); 422 col = gtk_tree_view_column_new_with_attributes(_("Name"), namerend, NULL); 423 gtk_tree_view_column_set_cell_data_func(col, namerend, dfname, NULL, NULL); 424 gtk_tree_view_column_set_expand(col, TRUE); 425 gtk_tree_view_append_column(GTK_TREE_VIEW(view), col); 426 427 progrend = tr_cell_renderer_torrent_new(); 428 /* this string is only used to determing the size of the progress bar */ 429 str = g_markup_printf_escaped("<big>%s</big>", _(" fnord fnord ")); 430 g_object_set(progrend, "label", str, NULL); 431 g_free(str); 432 col = gtk_tree_view_column_new_with_attributes(_("Progress"), progrend, NULL); 433 gtk_tree_view_column_set_cell_data_func(col, progrend, dfprog, NULL, NULL); 434 gtk_tree_view_append_column(GTK_TREE_VIEW(view), col); 435 436 /* XXX this shouldn't be necessary */ 437 g_signal_connect(view, "notify", G_CALLBACK(stylekludge), progrend); 438 439 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(view), TRUE); 440 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); 441 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(sel), GTK_SELECTION_MULTIPLE); 442 g_signal_connect(G_OBJECT(sel), "changed", G_CALLBACK(fixbuttons), data); 443 g_signal_connect(G_OBJECT(view), "button-press-event", 444 G_CALLBACK(listclick), data); 445 g_signal_connect(G_OBJECT(view), "popup-menu", G_CALLBACK(listpopup), data); 446 g_signal_connect(G_OBJECT(view), "row-activated", 447 G_CALLBACK(doubleclick), data); 448 gtk_widget_show_all(view); 449 450 return view; 451 } 346 452 347 453 gboolean … … 350 456 struct exitdata *edata; 351 457 tr_stat_t *st; 352 int ii; 458 GtkTreeIter iter; 459 tr_torrent_t *tor; 460 gboolean going; 353 461 354 462 if(0 >= data->timer) … … 356 464 data->timer = -1; 357 465 358 blocksigs(); 359 360 for(ii = tr_torrentStat(data->tr, &st); 0 < ii; ii--) { 361 if(TR_TORRENT_NEEDS_STOP(st[ii-1].status)) { 362 /*fprintf(stderr, "quit: stopping %i %s\n", ii, st[ii-1].info.name);*/ 363 tr_torrentStop(data->tr, ii - 1); 466 going = gtk_tree_model_get_iter_first(data->model, &iter); 467 while(going) { 468 gtk_tree_model_get(data->model, &iter, MC_TORRENT, &tor, -1); 469 st = tr_torrentStat(tor); 470 if(TR_STATUS_ACTIVE & st->status) { 471 tr_torrentStop(tor); 472 going = gtk_tree_model_iter_next(data->model, &iter); 364 473 } else { 365 /*fprintf(stderr, "quit: closing %i %s\n", ii, st[ii-1].info.name);*/366 tr_torrentClose(data->tr, ii - 1);474 tr_torrentClose(data->tr, tor); 475 going = gtk_list_store_remove(GTK_LIST_STORE(data->model), &iter); 367 476 } 368 477 } 369 free(st);370 371 unblocksigs();372 478 373 479 /* XXX should disable widgets or something */ … … 379 485 edata->timer = g_timeout_add(500, exitcheck, edata); 380 486 381 /*fprintf(stderr, "quit: starting timeout at %i\n", edata->started);*/382 383 487 /* returning FALSE means to destroy the window */ 384 488 return TRUE; … … 389 493 struct exitdata *data = gdata; 390 494 tr_stat_t *st; 391 int ii; 392 393 blocksigs(); 394 395 for(ii = tr_torrentStat(data->cbdata->tr, &st); 0 < ii; ii--) { 396 if(TR_STATUS_PAUSE & st[ii-1].status) { 397 /*fprintf(stderr, "quit: closing %i %s\n", ii, st[ii-1].info.name);*/ 398 tr_torrentClose(data->cbdata->tr, ii - 1); 495 GtkTreeIter iter; 496 tr_torrent_t *tor; 497 gboolean go; 498 499 go = gtk_tree_model_get_iter_first(data->cbdata->model, &iter); 500 while(go) { 501 gtk_tree_model_get(data->cbdata->model, &iter, MC_TORRENT, &tor, -1); 502 st = tr_torrentStat(tor); 503 if(!(TR_STATUS_PAUSE & st->status)) 504 go = gtk_tree_model_iter_next(data->cbdata->model, &iter); 505 else { 506 tr_torrentClose(data->cbdata->tr, tor); 507 go = gtk_list_store_remove(GTK_LIST_STORE(data->cbdata->model), &iter); 399 508 } 400 509 } 401 free(st); 402 403 /*fprintf(stderr, "quit: %i torrents left at %i\n", 404 tr_torrentCount(data->cbdata->tr), time(NULL));*/ 510 405 511 /* keep going if we still have torrents and haven't hit the exit timeout */ 406 512 if(0 < tr_torrentCount(data->cbdata->tr) && 407 513 time(NULL) - data->started < TRACKER_EXIT_TIMEOUT) { 514 assert(gtk_tree_model_get_iter_first(data->cbdata->model, &iter)); 408 515 updatemodel(data->cbdata); 409 unblocksigs();410 516 return TRUE; 411 517 } … … 417 523 data->timer = -1; 418 524 419 /*fprintf(stderr, "quit: giving up on %i torrents\n",420 tr_torrentCount(data->cbdata->tr));*/421 525 stoptransmission(data->cbdata->tr); 422 clearhandlers();423 unblocksigs();424 526 425 527 gtk_widget_destroy(GTK_WIDGET(data->cbdata->wind)); … … 432 534 433 535 void 434 stoptransmission(void *tr) { 435 while(0 < tr_torrentCount(tr)) 436 tr_torrentClose(tr, 0); 536 stoptransmission(tr_handle_t *tr) { 537 GList *list, *ii; 538 539 list = NULL; 540 tr_torrentIterate(tr, maketorrentlist, &list); 541 for(ii = g_list_first(list); NULL != ii; ii = ii->next) 542 tr_torrentClose(tr, ii->data); 543 g_list_free(list); 544 437 545 tr_close(tr); 438 546 } … … 501 609 deslashed = hostless; 502 610 /* finally, try to add it as a torrent */ 503 if(addtorrent(data ->tr, data->wind, deslashed, NULL, FALSE, &errs))611 if(addtorrent(data, deslashed, NULL, FALSE, &errs)) 504 612 gotfile = TRUE; 505 613 } … … 542 650 } 543 651 544 GtkWidget *545 makewind_toolbar(struct cbdata *data) {546 GtkWidget *bar = gtk_toolbar_new();547 GtkToolItem *item;548 unsigned int ii;549 550 gtk_toolbar_set_tooltips(GTK_TOOLBAR(bar), TRUE);551 gtk_toolbar_set_show_arrow(GTK_TOOLBAR(bar), FALSE);552 gtk_toolbar_set_style(GTK_TOOLBAR(bar), GTK_TOOLBAR_BOTH);553 554 data->buttons = g_new(GtkWidget*, ALEN(actionitems));555 556 for(ii = 0; ii < ALEN(actionitems); ii++) {557 item = gtk_tool_button_new_from_stock(actionitems[ii].id);558 data->buttons[ii] = GTK_WIDGET(item);559 gtk_tool_button_set_label(GTK_TOOL_BUTTON(item), gettext(actionitems[ii].name));560 gtk_tool_item_set_tooltip(GTK_TOOL_ITEM(item), GTK_TOOLBAR(bar)->tooltips,561 gettext(actionitems[ii].ttext), actionitems[ii].tpriv);562 g_object_set_data(G_OBJECT(item), LIST_ACTION,563 GINT_TO_POINTER(actionitems[ii].act));564 g_object_set_data(G_OBJECT(item), LIST_ACTION_FROM,565 GINT_TO_POINTER(FROM_BUTTON));566 g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(actionclick), data);567 gtk_toolbar_insert(GTK_TOOLBAR(bar), item, -1);568 }569 570 return bar;571 }572 573 /* XXX check for unused data in model */574 enum {MC_NAME, MC_SIZE, MC_STAT, MC_ERR, MC_PROG, MC_DRATE, MC_URATE,575 MC_ETA, MC_PEERS, MC_UPEERS, MC_DPEERS, MC_PIECES, MC_DOWN, MC_UP,576 MC_ROW_INDEX, MC_ROW_COUNT};577 578 GtkWidget *579 makewind_list(struct cbdata *data) {580 GType types[] = {581 /* info->name, info->totalSize, status, error, progress */582 G_TYPE_STRING, G_TYPE_UINT64, G_TYPE_INT, G_TYPE_STRING, G_TYPE_FLOAT,583 /* rateDownload, rateUpload, eta, peersTotal, peersUploading */584 G_TYPE_FLOAT, G_TYPE_FLOAT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT,585 /* peersDownloading, pieces, downloaded, uploaded */586 G_TYPE_INT, TR_TYPE_PIECES, G_TYPE_UINT64, G_TYPE_UINT64,587 /* index into the torrent array */588 G_TYPE_INT};589 GtkListStore *model;590 GtkWidget *view;591 GtkTreeViewColumn *col;592 GtkTreeSelection *sel;593 GtkCellRenderer *namerend, *progrend;594 char *str;595 596 assert(MC_ROW_COUNT == ALEN(types));597 598 model = gtk_list_store_newv(MC_ROW_COUNT, types);599 view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model));600 /* XXX do I need to worry about reference counts anywhere else? */601 g_object_unref(G_OBJECT(model));602 data->model = model;603 data->view = GTK_TREE_VIEW(view);604 605 namerend = gtk_cell_renderer_text_new();606 col = gtk_tree_view_column_new_with_attributes(_("Name"), namerend, NULL);607 gtk_tree_view_column_set_cell_data_func(col, namerend, dfname, NULL, NULL);608 gtk_tree_view_column_set_expand(col, TRUE);609 gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);610 611 progrend = tr_cell_renderer_torrent_new();612 /* this string is only used to determing the size of the progress bar */613 str = g_markup_printf_escaped("<big>%s</big>", _(" fnord fnord "));614 g_object_set(progrend, "label", str, NULL);615 g_free(str);616 col = gtk_tree_view_column_new_with_attributes(_("Progress"), progrend, NULL);617 gtk_tree_view_column_set_cell_data_func(col, progrend, dfprog, NULL, NULL);618 gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);619 620 /* XXX this shouldn't be necessary */621 g_signal_connect(view, "notify", G_CALLBACK(stylekludge), progrend);622 623 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(view), TRUE);624 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));625 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(sel), GTK_SELECTION_MULTIPLE);626 g_signal_connect(G_OBJECT(sel), "changed", G_CALLBACK(fixbuttons), data);627 g_signal_connect(G_OBJECT(view), "button-press-event",628 G_CALLBACK(listclick), data);629 g_signal_connect(G_OBJECT(view), "popup-menu", G_CALLBACK(listpopup), data);630 g_signal_connect(G_OBJECT(view), "row-activated",631 G_CALLBACK(doubleclick), data);632 gtk_widget_show_all(view);633 634 return view;635 }636 637 652 /* kludge to have the progress bars notice theme changes */ 638 653 static void … … 667 682 dfname(GtkTreeViewColumn *col SHUTUP, GtkCellRenderer *rend, 668 683 GtkTreeModel *model, GtkTreeIter *iter, gpointer gdata SHUTUP) { 669 char *name, *mb, * err, *str, *top, *bottom;684 char *name, *mb, *terr, *str, *top, *bottom; 670 685 guint64 size; 671 686 gfloat prog; 672 int status, eta, tpeers, upeers, dpeers; 673 674 /* XXX should I worry about gtk_tree_model_get failing? */ 687 int status, err, eta, tpeers, upeers, dpeers; 688 675 689 gtk_tree_model_get(model, iter, MC_NAME, &name, MC_STAT, &status, 676 MC_ SIZE, &size, MC_PROG, &prog, MC_ETA, &eta, MC_PEERS, &tpeers,677 MC_ UPEERS, &upeers, MC_DPEERS, &dpeers, -1);690 MC_ERR, &err, MC_SIZE, &size, MC_PROG, &prog, MC_ETA, &eta, 691 MC_PEERS, &tpeers, MC_UPEERS, &upeers, MC_DPEERS, &dpeers, -1); 678 692 679 693 if(0 > tpeers) … … 708 722 } 709 723 710 if( status & TR_TRACKER_ERROR) {711 gtk_tree_model_get(model, iter, MC_ ERR, &err, -1);712 bottom = g_strconcat(_("Error: "), err, NULL);713 g_free( err);724 if(TR_NOERROR != err) { 725 gtk_tree_model_get(model, iter, MC_TERR, &terr, -1); 726 bottom = g_strconcat(_("Error: "), terr, NULL); 727 g_free(terr); 714 728 } 715 729 else if(status & TR_STATUS_DOWNLOAD) … … 737 751 guint64 down, up; 738 752 739 /* XXX should I worry about gtk_tree_model_get failing? */740 753 gtk_tree_model_get(model, iter, MC_PROG, &prog, MC_DRATE, &dl, MC_URATE, &ul, 741 754 MC_DOWN, &down, MC_UP, &up, -1); … … 764 777 updatemodel(gpointer gdata) { 765 778 struct cbdata *data = gdata; 779 tr_torrent_t *tor; 766 780 tr_stat_t *st; 767 int ii, max;781 tr_info_t *in; 768 782 GtkTreeIter iter; 769 783 float up, down; 770 784 char *upstr, *downstr, *str; 771 785 772 blocksigs(); 773 774 max = tr_torrentStat(data->tr, &st); 775 for(ii = 0; ii < max; ii++) { 776 if(!(ii ? gtk_tree_model_iter_next(GTK_TREE_MODEL(data->model), &iter) : 777 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(data->model), &iter))) 778 gtk_list_store_append(data->model, &iter); 779 /* XXX find out if setting the same data emits changed signal */ 780 gtk_list_store_set( 781 data->model, &iter, MC_ROW_INDEX, ii, 782 MC_NAME, st[ii].info.name, MC_SIZE, st[ii].info.totalSize, 783 MC_STAT, st[ii].status, MC_ERR, st[ii].error, MC_PROG, st[ii].progress, 784 MC_DRATE, st[ii].rateDownload, MC_URATE, st[ii].rateUpload, 785 MC_ETA, st[ii].eta, MC_PEERS, st[ii].peersTotal, 786 MC_UPEERS, st[ii].peersUploading, MC_DPEERS, st[ii].peersDownloading, 787 MC_DOWN, st[ii].downloaded, MC_UP, st[ii].uploaded, -1); 788 } 789 free(st); 790 791 /* remove any excess rows */ 792 if(ii ? gtk_tree_model_iter_next(GTK_TREE_MODEL(data->model), &iter) : 793 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(data->model), &iter)) 794 while(gtk_list_store_remove(data->model, &iter)) 795 ; 786 if(0 < global_sigcount) { 787 stoptransmission(data->tr); 788 global_sigcount = SIGCOUNT_MAX; 789 raise(global_lastsig); 790 } 791 792 if(gtk_tree_model_get_iter_first(data->model, &iter)) { 793 do { 794 gtk_tree_model_get(data->model, &iter, MC_TORRENT, &tor, -1); 795 st = tr_torrentStat(tor); 796 in = tr_torrentInfo(tor); 797 /* XXX find out if setting the same data emits changed signal */ 798 gtk_list_store_set(GTK_LIST_STORE(data->model), &iter, MC_NAME, in->name, 799 MC_SIZE, in->totalSize, MC_STAT, st->status, MC_ERR, st->error, 800 MC_TERR, st->trackerError, MC_PROG, st->progress, 801 MC_DRATE, st->rateDownload, MC_URATE, st->rateUpload, MC_ETA, st->eta, 802 MC_PEERS, st->peersTotal, MC_UPEERS, st->peersUploading, 803 MC_DPEERS, st->peersDownloading, MC_DOWN, st->downloaded, 804 MC_UP, st->uploaded, -1); 805 } while(gtk_tree_model_iter_next(data->model, &iter)); 806 } 796 807 797 808 /* update the status bar */ … … 810 821 fixbuttons(NULL, data); 811 822 812 unblocksigs();813 814 823 return TRUE; 815 824 } … … 822 831 GtkTreePath *path; 823 832 GtkTreeIter iter; 824 int index, status; 833 int status; 834 gpointer tor; 825 835 GList *ids; 826 836 … … 832 842 dopopupmenu(event, data, NULL, 0); 833 843 else { 834 if(gtk_tree_model_get_iter( GTK_TREE_MODEL(data->model), &iter, path)) {844 if(gtk_tree_model_get_iter(data->model, &iter, path)) { 835 845 /* get ID and status for the right-clicked row */ 836 gtk_tree_model_get( GTK_TREE_MODEL(data->model), &iter,837 MC_ ROW_INDEX, &index, MC_STAT, &status, -1);846 gtk_tree_model_get(data->model, &iter, MC_TORRENT, &tor, 847 MC_STAT, &status, -1); 838 848 /* get a list of selected IDs */ 839 849 ids = NULL; 840 850 gtk_tree_selection_selected_foreach(sel, makeidlist, &ids); 841 851 /* is the clicked row selected? */ 842 if(NULL == g_list_find(ids, GINT_TO_POINTER(index))) {852 if(NULL == g_list_find(ids, tor)) { 843 853 /* no, do the popup for just the clicked row */ 844 854 g_list_free(ids); 845 dopopupmenu(event, data, g_list_append(NULL, GINT_TO_POINTER(index)), 846 status); 855 dopopupmenu(event, data, g_list_append(NULL, tor), status); 847 856 } else { 848 857 /* yes, do the popup for all the selected rows */ … … 863 872 struct cbdata *data = gdata; 864 873 GtkTreeSelection *sel = gtk_tree_view_get_selection(data->view); 865 GtkTreeModel *model;866 874 GList *ids; 867 875 int status; … … 870 878 dopopupmenu(NULL, data, NULL, 0); 871 879 else { 872 assert(model == GTK_TREE_MODEL(data->model));873 880 status = 0; 874 881 gtk_tree_selection_selected_foreach(sel, orstatus, &status); … … 901 908 GINT_TO_POINTER(FROM_POPUP)); 902 909 /* set a glist of selected torrent's IDs */ 903 g_object_set_data(G_OBJECT(item), LIST_I NDEX, ids);910 g_object_set_data(G_OBJECT(item), LIST_IDS, ids); 904 911 /* set the menu widget, so the activate handler can destroy it */ 905 912 g_object_set_data(G_OBJECT(item), LIST_MENU_WIDGET, menu); … … 910 917 911 918 /* set up the glist to be freed when the menu is destroyed */ 912 g_object_set_data_full(G_OBJECT(menu), LIST_I NDEX, ids,919 g_object_set_data_full(G_OBJECT(menu), LIST_IDS, ids, 913 920 (GDestroyNotify)g_list_free); 914 921 … … 936 943 enum listfrom from = 937 944 GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), LIST_ACTION_FROM)); 938 int index, count;939 945 unsigned int actindex; 940 946 tr_stat_t *sb; 941 947 GList *ids, *ii; 948 tr_torrent_t *tor; 942 949 gboolean updatesave; 950 GtkTreeIter iter; 943 951 944 952 /* destroy the popup menu, if any */ … … 948 956 switch(act) { 949 957 case ACT_OPEN: 950 makeaddwind( addtorrent, data->wind, data->tr, addedtorrents, data);958 makeaddwind(data->wind, addtorrent, addedtorrents, data); 951 959 return; 952 960 case ACT_PREF: … … 962 970 ids = NULL; 963 971 gtk_tree_selection_selected_foreach(sel, makeidlist, &ids); 964 /* XXX should I assert(0 <= index) to insure a row was selected? */965 972 break; 966 973 case FROM_POPUP: 967 ids = g_object_get_data(G_OBJECT(widget), LIST_I NDEX);974 ids = g_object_get_data(G_OBJECT(widget), LIST_IDS); 968 975 break; 969 976 default: … … 977 984 assert(actindex < ALEN(actionitems)); 978 985 979 blocksigs();980 986 updatesave = FALSE; 981 count = tr_torrentStat(data->tr, &sb);982 987 983 988 for(ii = g_list_sort(ids, intrevcmp); NULL != ii; ii = ii->next) { 984 index = GPOINTER_TO_INT(ii->data); 985 if(index >= count) { 986 assert(!"illegal torrent id"); 987 continue; 988 } 989 tor = ii->data; 990 sb = tr_torrentStat(tor); 991 989 992 /* check if this action is valid for this torrent */ 990 993 if(actionitems[actindex].nomenu || 991 994 (actionitems[actindex].avail && 992 !(actionitems[actindex].avail & sb [index].status)))995 !(actionitems[actindex].avail & sb->status))) 993 996 continue; 994 997 995 998 switch(act) { 996 999 case ACT_START: 997 tr_torrentStart( data->tr, index);1000 tr_torrentStart(tor); 998 1001 updatesave = TRUE; 999 1002 break; 1000 1003 case ACT_STOP: 1001 tr_torrentStop( data->tr, index);1004 tr_torrentStop(tor); 1002 1005 updatesave = TRUE; 1003 1006 break; 1004 1007 case ACT_DELETE: 1005 if(TR_TORRENT_NEEDS_STOP(sb[index].status)) 1006 tr_torrentStop(data->tr, index); 1007 tr_torrentClose(data->tr, index); 1008 if(TR_STATUS_ACTIVE & sb->status) 1009 tr_torrentStop(tor); 1010 tr_torrentClose(data->tr, tor); 1011 findtorrent(data->model, tor, &iter); 1012 gtk_list_store_remove(GTK_LIST_STORE(data->model), &iter); 1008 1013 updatesave = TRUE; 1009 1014 /* XXX should only unselect deleted rows */ 1010 gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(data->view)); 1015 gtk_tree_selection_unselect_all( 1016 gtk_tree_view_get_selection(data->view)); 1011 1017 break; 1012 1018 case ACT_INFO: 1013 makeinfowind(data->wind, data->tr, index);1019 makeinfowind(data->wind, tor); 1014 1020 break; 1015 1021 default: … … 1018 1024 } 1019 1025 } 1020 free(sb);1021 1026 1022 1027 if(updatesave) { 1023 savetorrents(data->tr, data->wind , -1, NULL);1028 savetorrents(data->tr, data->wind); 1024 1029 updatemodel(data); 1025 1030 } 1026 1027 unblocksigs();1028 1031 1029 1032 if(FROM_BUTTON == from) 1030 1033 g_list_free(ids); 1034 } 1035 1036 void 1037 findtorrent(GtkTreeModel *model, tr_torrent_t *tor, GtkTreeIter *iter) { 1038 gpointer ptr; 1039 1040 if(gtk_tree_model_get_iter_first(model, iter)) { 1041 do { 1042 gtk_tree_model_get(model, iter, MC_TORRENT, &ptr, -1); 1043 if(tor == ptr) 1044 return; 1045 } while(gtk_tree_model_iter_next(model, iter)); 1046 } 1047 1048 assert(!"torrent not found"); 1031 1049 } 1032 1050 … … 1049 1067 struct cbdata *data = gdata; 1050 1068 GtkTreeIter iter; 1051 int index; 1052 1053 if(gtk_tree_model_get_iter(GTK_TREE_MODEL(data->model), &iter, path)) { 1054 gtk_tree_model_get(GTK_TREE_MODEL(data->model), &iter, 1055 MC_ROW_INDEX, &index, -1); 1056 makeinfowind(data->wind, data->tr, index); 1057 } 1058 } 1059 1060 gboolean 1061 addtorrent(tr_handle_t *tr, GtkWindow *parentwind, const char *torrent, 1062 const char *dir, gboolean paused, GList **errs) { 1069 tr_torrent_t *tor; 1070 1071 if(gtk_tree_model_get_iter(data->model, &iter, path)) { 1072 gtk_tree_model_get(data->model, &iter, MC_TORRENT, &tor, -1); 1073 makeinfowind(data->wind, tor); 1074 } 1075 } 1076 1077 gboolean 1078 addtorrent(void *vdata, const char *torrent, const char *dir, gboolean paused, 1079 GList **errs) { 1080 const struct { const int err; const char *msg; } errstrs[] = { 1081 {TR_EINVALID, N_("not a valid torrent file")}, 1082 {TR_EDUPLICATE, N_("torrent is already open")}, 1083 }; 1084 struct cbdata *data = vdata; 1085 tr_torrent_t *new; 1063 1086 char *wd; 1087 int err; 1088 unsigned int ii; 1089 GtkTreeIter iter; 1064 1090 1065 1091 if(NULL == dir && NULL != (dir = cf_getpref(PREF_DIR))) { 1066 1092 if(!mkdir_p(dir, 0777)) { 1067 errmsg( parentwind, _("Failed to create the directory %s:\n%s"),1093 errmsg(data->wind, _("Failed to create the directory %s:\n%s"), 1068 1094 dir, strerror(errno)); 1069 1095 return FALSE; … … 1071 1097 } 1072 1098 1073 blocksigs(); 1074 1075 if(0 != tr_torrentInit(tr, torrent)) { 1076 unblocksigs(); 1077 /* XXX would be nice to have errno strings, are they printed to stdout? */ 1078 if(NULL == errs) 1079 errmsg(parentwind, _("Failed to load the torrent file %s"), torrent); 1080 else 1081 *errs = g_list_append(*errs, g_strdup(torrent)); 1099 if(NULL == (new = tr_torrentInit(data->tr, torrent, &err))) { 1100 for(ii = 0; ii < ALEN(errstrs); ii++) 1101 if(err == errstrs[ii].err) 1102 break; 1103 if(NULL == errs) { 1104 if(ii == ALEN(errstrs)) 1105 errmsg(data->wind, _("Failed to load the torrent file %s"), torrent); 1106 else 1107 errmsg(data->wind, _("Failed to load the torrent file %s: %s"), 1108 torrent, gettext(errstrs[ii].msg)); 1109 } else { 1110 if(ii == ALEN(errstrs)) 1111 *errs = g_list_append(*errs, g_strdup(torrent)); 1112 else 1113 *errs = g_list_append(*errs, g_strdup_printf(_("%s (%s)"), 1114 torrent, gettext(errstrs[ii].msg))); 1115 } 1082 1116 return FALSE; 1083 1117 } 1084 1118 1119 gtk_list_store_append(GTK_LIST_STORE(data->model), &iter); 1120 gtk_list_store_set(GTK_LIST_STORE(data->model), &iter, MC_TORRENT, new, -1); 1121 1085 1122 if(NULL != dir) 1086 tr_torrentSetFolder( tr, tr_torrentCount(tr) - 1, dir);1123 tr_torrentSetFolder(new, dir); 1087 1124 else { 1088 1125 wd = g_new(char, MAXPATHLEN + 1); 1089 1126 if(NULL == getcwd(wd, MAXPATHLEN + 1)) 1090 tr_torrentSetFolder( tr, tr_torrentCount(tr) - 1, ".");1127 tr_torrentSetFolder(new, "."); 1091 1128 else { 1092 tr_torrentSetFolder( tr, tr_torrentCount(tr) - 1, wd);1129 tr_torrentSetFolder(new, wd); 1093 1130 free(wd); 1094 1131 } … … 1096 1133 1097 1134 if(!paused) 1098 tr_torrentStart(tr, tr_torrentCount(tr) - 1); 1099 1100 unblocksigs(); 1135 tr_torrentStart(new); 1101 1136 1102 1137 return TRUE; … … 1108 1143 1109 1144 updatemodel(data); 1110 savetorrents(data->tr, data->wind, -1, NULL); 1111 } 1112 1113 gboolean 1114 savetorrents(tr_handle_t *tr, GtkWindow *wind, int count, tr_stat_t *stat) { 1145 savetorrents(data->tr, data->wind); 1146 } 1147 1148 gboolean 1149 savetorrents(tr_handle_t *tr, GtkWindow *wind) { 1150 GList *torrents; 1115 1151 char *errstr; 1116 tr_stat_t *st;1117 1152 gboolean ret; 1118 1153 1119 assert(NULL != tr || 0 <= count); 1120 1121 if(0 <= count) 1122 ret = cf_savestate(count, stat, &errstr); 1123 else { 1124 blocksigs(); 1125 count = tr_torrentStat(tr, &st); 1126 unblocksigs(); 1127 ret = cf_savestate(count, st, &errstr); 1128 free(st); 1129 } 1130 1131 if(!ret) { 1154 torrents = NULL; 1155 tr_torrentIterate(tr, maketorrentlist, &torrents); 1156 1157 if(!(ret = cf_savestate(torrents, &errstr))) { 1132 1158 errmsg(wind, "%s", errstr); 1133 1159 g_free(errstr); 1134 1160 } 1161 1162 g_list_free(torrents); 1135 1163 1136 1164 return ret; … … 1152 1180 gpointer gdata) { 1153 1181 GList **ids = gdata; 1154 int index; 1155 1156 gtk_tree_model_get(model, iter, MC_ROW_INDEX, &index, -1); 1157 *ids = g_list_append(*ids, GINT_TO_POINTER(index)); 1158 } 1182 gpointer ptr; 1183 1184 gtk_tree_model_get(model, iter, MC_TORRENT, &ptr, -1); 1185 *ids = g_list_append(*ids, ptr); 1186 } 1187 1188 void 1189 maketorrentlist(tr_torrent_t *tor, void *data) { 1190 GList **list = data; 1191 1192 *list = g_list_append(*list, tor); 1193 } 1194 1195 void 1196 setupsighandlers(void) { 1197 int sigs[] = {SIGHUP, SIGINT, SIGQUIT, SIGTERM, SIGUSR1, SIGUSR2}; 1198 struct sigaction sa; 1199 unsigned int ii; 1200 1201 bzero(&sa, sizeof(sa)); 1202 sa.sa_handler = fatalsig; 1203 for(ii = 0; ii < ALEN(sigs); ii++) 1204 sigaction(sigs[ii], &sa, NULL); 1205 } 1206 1207 void 1208 fatalsig(int sig) { 1209 struct sigaction sa; 1210 1211 global_lastsig = sig; 1212 1213 if(SIGCOUNT_MAX <= ++global_sigcount) { 1214 bzero(&sa, sizeof(sa)); 1215 sa.sa_handler = SIG_DFL; 1216 sigaction(sig, &sa, NULL); 1217 raise(sig); 1218 } 1219 } -
branches/new_api/gtk/po/transmission-gtk.pot
r117 r161 9 9 "Project-Id-Version: PACKAGE VERSION\n" 10 10 "Report-Msgid-Bugs-To: \n" 11 "POT-Creation-Date: 2006-0 2-10 00:50-0500\n"11 "POT-Creation-Date: 2006-03-20 11:30-0800\n" 12 12 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 13 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" … … 44 44 msgstr "" 45 45 46 #: conf.c:115 dialogs.c:19 1 main.c:106546 #: conf.c:115 dialogs.c:190 main.c:1093 47 47 #, c-format 48 48 msgid "" … … 70 70 msgstr "" 71 71 72 #: conf.c:233 conf.c:43 272 #: conf.c:233 conf.c:434 73 73 #, c-format 74 74 msgid "" … … 77 77 msgstr "" 78 78 79 #: conf.c:253 conf.c:47 279 #: conf.c:253 conf.c:476 80 80 #, c-format 81 81 msgid "" … … 84 84 msgstr "" 85 85 86 #: conf.c:260 conf.c:4 7986 #: conf.c:260 conf.c:483 87 87 #, c-format 88 88 msgid "" … … 91 91 msgstr "" 92 92 93 #: dialogs.c:7 693 #: dialogs.c:75 94 94 #, c-format 95 95 msgid "%s Preferences" 96 96 msgstr "" 97 97 98 #: dialogs.c:8 498 #: dialogs.c:83 99 99 msgid "_Limit upload speed" 100 100 msgstr "" 101 101 102 #: dialogs.c:8 7102 #: dialogs.c:86 103 103 msgid "Choose download directory" 104 104 msgstr "" 105 105 106 106 #. limit label and entry 107 #: dialogs.c:12 1107 #: dialogs.c:120 108 108 msgid "Maximum _upload speed:" 109 109 msgstr "" 110 110 111 111 #. directory label and chooser 112 #: dialogs.c:13 5112 #: dialogs.c:134 113 113 msgid "_Download directory:" 114 114 msgstr "" 115 115 116 116 #. port label and entry 117 #: dialogs.c:14 4117 #: dialogs.c:143 118 118 msgid "Listening _port:" 119 119 msgstr "" … … 135 135 msgstr "" 136 136 137 #: dialogs.c:28 5137 #: dialogs.c:284 138 138 msgid "Torrent files" 139 139 msgstr "" 140 140 141 #: dialogs.c:28 7141 #: dialogs.c:286 142 142 msgid "All files" 143 143 msgstr "" … … 192 192 msgstr "" 193 193 194 #: main.c:1 55194 #: main.c:164 195 195 msgid "Add" 196 196 msgstr "" 197 197 198 #: main.c:1 56198 #: main.c:165 199 199 msgid "Add a new torrent" 200 200 msgstr "" 201 201 202 #: main.c:1 57202 #: main.c:166 203 203 msgid "Start" 204 204 msgstr "" 205 205 206 #: main.c:1 59206 #: main.c:168 207 207 msgid "Start a torrent that is not running" 208 208 msgstr "" 209 209 210 #: main.c:16 0210 #: main.c:169 211 211 msgid "Stop" 212 212 msgstr "" 213 213 214 #: main.c:1 62214 #: main.c:171 215 215 msgid "Stop a torrent that is running" 216 216 msgstr "" 217 217 218 #: main.c:1 63218 #: main.c:172 219 219 msgid "Remove" 220 220 msgstr "" 221 221 222 #: main.c:1 64222 #: main.c:173 223 223 msgid "Remove a torrent" 224 224 msgstr "" 225 225 226 #: main.c:1 65226 #: main.c:174 227 227 msgid "Properties" 228 228 msgstr "" 229 229 230 #: main.c:1 66230 #: main.c:175 231 231 msgid "Show additional information about a torrent" 232 232 msgstr "" 233 233 234 #: main.c:1 67234 #: main.c:176 235 235 msgid "Preferences" 236 236 msgstr "" 237 237 238 #: main.c:1 68238 #: main.c:177 239 239 msgid "Customize application behavior" 240 240 msgstr "" 241 241 242 #: main.c: 186242 #: main.c:203 243 243 msgid "Transmission" 244 244 msgstr "" 245 245 246 #: main.c:3 16 main.c:518 main.c:1077246 #: main.c:331 main.c:626 main.c:1105 247 247 #, c-format 248 248 msgid "Failed to load the torrent file %s" … … 253 253 msgstr[1] "" 254 254 255 #: main.c: 606255 #: main.c:422 256 256 msgid "Name" 257 257 msgstr "" 258 258 259 259 #. this string is only used to determing the size of the progress bar 260 #: main.c: 613260 #: main.c:429 261 261 msgid " fnord fnord " 262 262 msgstr "" 263 263 264 #: main.c: 616264 #: main.c:432 265 265 msgid "Progress" 266 266 msgstr "" 267 267 268 #: main.c: 691268 #: main.c:703 269 269 #, c-format 270 270 msgid "Checking existing files (%.1f%%)" 271 271 msgstr "" 272 272 273 #: main.c:693 273 #: main.c:706 274 #, c-format 275 msgid "Finishing in --:--:-- (%.1f%%)" 276 msgstr "" 277 278 #: main.c:708 274 279 #, c-format 275 280 msgid "Finishing in %02i:%02i:%02i (%.1f%%)" 276 281 msgstr "" 277 282 278 #: main.c: 696283 #: main.c:712 279 284 #, c-format 280 285 msgid "Seeding, uploading to %d of %d peer" … … 283 288 msgstr[1] "" 284 289 285 #: main.c:7 00290 #: main.c:716 286 291 msgid "Stopping..." 287 292 msgstr "" 288 293 289 #: main.c:7 02294 #: main.c:718 290 295 #, c-format 291 296 msgid "Stopped (%.1f%%)" 292 297 msgstr "" 293 298 294 #: main.c:7 10299 #: main.c:726 295 300 msgid "Error: " 296 301 msgstr "" 297 302 298 #: main.c:7 14303 #: main.c:730 299 304 #, c-format 300 305 msgid "Downloading from %i of %i peer" … … 303 308 msgstr[1] "" 304 309 305 #: main.c:7 48310 #: main.c:763 306 311 #, c-format 307 312 msgid "" … … 310 315 msgstr "" 311 316 312 #: main.c:7 51317 #: main.c:766 313 318 #, c-format 314 319 msgid "" … … 317 322 msgstr "" 318 323 319 #: main.c: 799324 #: main.c:812 320 325 #, c-format 321 326 msgid " Total DL: %s/s Total UL: %s/s" 322 327 msgstr "" 323 328 329 #: main.c:1081 330 msgid "not a valid torrent file" 331 msgstr "" 332 333 #: main.c:1082 334 msgid "torrent is already open" 335 msgstr "" 336 337 #: main.c:1107 338 #, c-format 339 msgid "Failed to load the torrent file %s: %s" 340 msgstr "" 341 342 #: main.c:1113 343 #, c-format 344 msgid "%s (%s)" 345 msgstr "" 346 324 347 #: util.c:63 325 348 msgid "B" … … 350 373 msgstr "" 351 374 352 #: util.c:8 7375 #: util.c:88 353 376 msgid "N/A" 354 377 msgstr "" 355 378 356 379 #. this is a UTF-8 infinity symbol 357 #: util.c:9 1380 #: util.c:92 358 381 msgid "â" 359 382 msgstr "" -
branches/new_api/gtk/util.c
r131 r161 40 40 41 41 static void 42 sigexithandler(int sig);43 static void44 42 errcb(GtkWidget *wind, int resp, gpointer data); 45 43 … … 186 184 } 187 185 188 static int exit_sigs[] = {SIGHUP, SIGINT, SIGQUIT, SIGTERM, SIGUSR1, SIGUSR2};189 static callbackfunc_t exit_func = NULL;190 static void *exit_data = NULL;191 static int exit_block_level = 0;192 193 void194 setuphandlers(callbackfunc_t func, void *data) {195 struct sigaction sa;196 unsigned int ii;197 198 exit_data = data;199 exit_func = func;200 201 bzero(&sa, sizeof(sa));202 sa.sa_handler = sigexithandler;203 for(ii = 0; ii < ALEN(exit_sigs); ii++)204 sigaction(exit_sigs[ii], &sa, NULL);205 }206 207 void208 clearhandlers(void) {209 struct sigaction sa;210 unsigned int ii;211 212 bzero(&sa, sizeof(sa));213 sa.sa_handler = SIG_DFL;214 for(ii = 0; ii < ALEN(exit_sigs); ii++)215 sigaction(exit_sigs[ii], &sa, NULL);216 }217 218 static void219 sigexithandler(int sig) {220 exit_func(exit_data);221 clearhandlers();222 raise(sig);223 }224 225 void226 blocksigs(void) {227 sigset_t mask;228 unsigned int ii;229 230 if(0 < (exit_block_level++))231 return;232 233 sigemptyset(&mask);234 for(ii = 0; ii < ALEN(exit_sigs); ii++)235 sigaddset(&mask, exit_sigs[ii]);236 sigprocmask(SIG_BLOCK, &mask, NULL);237 }238 239 void240 unblocksigs(void) {241 sigset_t mask;242 unsigned int ii;243 244 if(0 < (--exit_block_level))245 return;246 247 sigemptyset(&mask);248 for(ii = 0; ii < ALEN(exit_sigs); ii++)249 sigaddset(&mask, exit_sigs[ii]);250 sigprocmask(SIG_UNBLOCK, &mask, NULL);251 }252 253 186 GtkWidget * 254 187 errmsg(GtkWindow *wind, const char *format, ...) { -
branches/new_api/gtk/util.h
r131 r161 71 71 urldecode(const char *str, int len); 72 72 73 /* set up a handler for various fatal signals */74 void75 setuphandlers(callbackfunc_t func, void *data);76 77 /* clear the handlers for fatal signals */78 void79 clearhandlers(void);80 81 /* blocks and unblocks delivery of fatal signals. calls to these82 functions can be nested as long as unblocksigs() is called exactly83 as many times as blocksigs(). only the first blocksigs() will84 block signals and only the last unblocksigs() will unblock them. */85 void86 blocksigs(void);87 void88 unblocksigs(void);89 90 73 /* if wind is NULL then you must call gtk_widget_show on the returned widget */ 91 74
Note: See TracChangeset
for help on using the changeset viewer.