Changeset 7 for trunk/gtk


Ignore:
Timestamp:
Jan 12, 2006, 6:40:47 PM (16 years ago)
Author:
root
Message:

Update 2005-11-24

Location:
trunk/gtk
Files:
2 added
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/gtk/Jamfile

    r6 r7  
    11SubDir TOP gtk ;
    22
    3 GTK_SRC = conf.c main.c util.c ;
     3GTK_SRC = conf.c main.c prefs.c util.c ;
    44
    55Main          transmission-gtk   : $(GTK_SRC) ;
  • trunk/gtk/conf.c

    r5 r7  
    4040#include "conf.h"
    4141#include "transmission.h"
     42#include "util.h"
    4243
    4344#define FILE_LOCK               "gtk_lock"
     
    160161    goto done;
    161162  }
    162   /*g_io_channel_set_encoding(io, NULL, NULL);*/
    163163  g_io_channel_set_line_term(io, &term, 1);
    164164
     
    210210  g_tree_insert(prefs, g_strdup(name), g_strdup(value));
    211211
    212   return writeprefs(errstr);
     212  if(NULL != errstr)
     213    return writeprefs(errstr);
     214  else
     215    return TRUE;
    213216}
    214217
     
    237240  }
    238241
     242#ifdef NDEBUG
     243  ftruncate(fd, 0);
     244#else
     245  assert(0 == ftruncate(fd, 0));
     246#endif
     247
    239248  info.err = NULL;
    240249  io = g_io_channel_unix_new(fd);
    241   /*g_io_channel_set_encoding(io, NULL, NULL);*/
    242250  g_io_channel_set_close_on_unref(io, TRUE);
    243251
     
    319327    goto done;
    320328  }
    321   /*g_io_channel_set_encoding(io, NULL, NULL);*/
    322329  g_io_channel_set_line_term(io, &term, 1);
    323330
     
    368375  char *start, *end;
    369376
     377  /* skip any leading whitespace */
    370378  while(isspace(*line))
    371379    line++;
    372380
    373   if(NULL == (start = strchr(line, '=')))
     381  /* walk over the key, which may be alphanumerics as well as - or _ */
     382  for(start = line; isalnum(*start) || '_' == *start || '-' == *start; start++)
     383    ;
     384
     385  /* they key must be immediately followed by an = */
     386  if('=' != *start)
    374387    return NULL;
    375 
    376   while(isspace(*(++start)))
    377     ;
    378 
    379   if('"' != *start)
     388  *(start++) = '\0';
     389
     390  /* then the opening quote for the value */
     391  if('"' != *(start++))
    380392    return NULL;
    381393
    382   for(end = ++start; '\0' != *end && '"' != *end; end++)
     394  /* walk over the value */
     395  for(end = start; '\0' != *end && '"' != *end; end++)
     396    /* skip over escaped quotes */
    383397    if('\\' == *end && '\0' != *(end + 1))
    384398      end++;
    385399
     400  /* make sure we didn't hit the end of the string */
    386401  if('"' != *end)
    387402    return NULL;
    388 
    389   if(0 == memcmp(line, "torrent", sizeof("torrent") - 1)) {
    390     state->ts_torrent = g_new(char, end - start + 1);
    391     memcpy(state->ts_torrent, start, end - start);
    392     state->ts_torrent[end - start] = '\0';
    393   }
    394   else if(0 == memcmp(line, "dir", sizeof("dir") - 1)) {
    395     state->ts_directory = g_new(char, end - start + 1);
    396     memcpy(state->ts_directory, start, end - start);
    397     state->ts_directory[end - start] = '\0';
    398   }
    399   else if(0 == memcmp(line, "paused", sizeof("paused") - 1)) {
    400     state->ts_paused = (0 == memcmp("yes", start, end - start));
    401   }
    402 
     403  *end = '\0';
     404
     405  /* if it's a key we recognize then save the data */
     406  if(0 == strcmp(line, "torrent"))
     407    state->ts_torrent = g_strcompress(start);
     408  else if(0 == strcmp(line, "dir"))
     409    state->ts_directory = g_strcompress(start);
     410  else if(0 == strcmp(line, "paused"))
     411    state->ts_paused = strbool(start);
     412
     413  /* return a pointer to just past the end of the value */
    403414  return end + 1;
    404415}
    405416
    406 /* XXX need to save download directory, also maybe running/stopped state */
    407417gboolean
    408418cf_savestate(int count, tr_stat_t *torrents, char **errstr) {
     
    426436  }
    427437
     438#ifdef NDEBUG
     439  ftruncate(fd, 0);
     440#else
     441  assert(0 == ftruncate(fd, 0));
     442#endif
     443
    428444  io = g_io_channel_unix_new(fd);
     445  g_io_channel_set_close_on_unref(io, TRUE);
     446
    429447  /* XXX what the hell should I be doing about unicode? */
    430   /*g_io_channel_set_encoding(io, NULL, NULL);*/
    431   g_io_channel_set_close_on_unref(io, TRUE);
    432448
    433449  err = NULL;
  • trunk/gtk/conf.h

    r5 r7  
    4444const char *
    4545cf_getpref(const char *name);
     46/* if errstr is NULL then prefs will not be saved */
    4647gboolean
    4748cf_setpref(const char *name, const char *value, char **errstr);
  • trunk/gtk/main.c

    r5 r7  
    2525*/
    2626
     27#include <sys/param.h>
    2728#include <assert.h>
     29#include <errno.h>
    2830#include <string.h>
    2931#include <stdio.h>
    3032#include <stdlib.h>
    31 #include <sys/param.h>
    3233#include <time.h>
    3334#include <unistd.h>
     
    3637
    3738#include "conf.h"
     39#include "prefs.h"
    3840#include "transmission.h"
    3941#include "util.h"
     
    4345struct cbdata {
    4446  tr_handle_t *tr;
    45   GtkWidget *wind;
     47  GtkWindow *wind;
    4648  GtkListStore *model;
    4749  GtkTreeView *view;
     
    6062
    6163void
    62 readargs(int argc, char **argv, int *port, int *limit);
    63 void
    6464maketypes(void);
    6565gpointer
     
    9393makeaddwind(struct cbdata *data);
    9494gboolean
    95 addtorrent(tr_handle_t *tr, GtkWidget *parentwind, const char *torrent,
     95addtorrent(tr_handle_t *tr, GtkWindow *parentwind, const char *torrent,
    9696           const char *dir, gboolean paused);
    9797void
     
    102102makeinfowind(struct cbdata *data, int index);
    103103gboolean
    104 savetorrents(tr_handle_t *tr, GtkWidget *wind, int count, tr_stat_t *stat);
     104savetorrents(tr_handle_t *tr, GtkWindow *wind, int count, tr_stat_t *stat);
    105105
    106106#define TR_TYPE_PIECES_NAME     "tr-type-pieces"
     
    110110
    111111#define LIST_ACTION           "torrent-list-action"
    112 enum listact { ACT_OPEN, ACT_START, ACT_STOP, ACT_DELETE, ACT_INFO };
     112enum listact { ACT_OPEN, ACT_START, ACT_STOP, ACT_DELETE, ACT_INFO, ACT_PREF };
    113113#define LIST_ACTION_FROM      "torrent-list-action-from"
    114114enum listfrom { FROM_BUTTON, FROM_POPUP };
     
    129129  {4,  "Properties",  GTK_STOCK_PROPERTIES,   ACT_INFO,
    130130   "Get additional information for a torrent", "XXX"},
     131  {5,  "Preferences", GTK_STOCK_PREFERENCES,  ACT_PREF,
     132   "Open preferences dialog", "XXX"},
    131133};
    132134
     
    136138  GtkWidget *mainwind, *preferr, *stateerr;
    137139  char *err;
    138   int port, limit;
    139140  tr_handle_t *tr;
    140141  GList *saved;
     142  const char *pref;
     143  long intval;
    141144
    142145  gtk_init(&argc, &argv);
    143   readargs(argc, argv, &port, &limit);
    144146
    145147  tr = tr_init();
     
    153155
    154156      if(!cf_loadprefs(&err)) {
    155         preferr = errmsg(mainwind, "%s", err);
     157        preferr = errmsg(GTK_WINDOW(mainwind), "%s", err);
    156158        g_free(err);
    157159      }
    158160      saved = cf_loadstate(&err);
    159161      if(NULL != err) {
    160         stateerr = errmsg(mainwind, "%s", err);
     162        stateerr = errmsg(GTK_WINDOW(mainwind), "%s", err);
    161163        g_free(err);
    162164      }
    163165
    164       /* XXX need to remove port and limit options and make them prefs */
    165       /* XXX need prefs gui */
    166       /* XXX need default save dir pref */
    167 
    168       if(0 != port)
    169         tr_setBindPort(tr, port);
    170       if(0 != limit)
    171         tr_setUploadLimit(tr, limit);
     166      /* set the upload limit */
     167      setlimit(tr);
     168
     169      /* set the listening port */
     170      if(NULL != (pref = cf_getpref(PREF_PORT)) &&
     171         0 < (intval = strtol(pref, NULL, 10)) && 0xffff >= intval)
     172        tr_setBindPort(tr, intval);
    172173
    173174      maketypes();
     
    179180        gtk_widget_show_all(stateerr);
    180181    } else {
    181       errmsg_full(NULL, (errfunc_t)gtk_main_quit, NULL, "%s", err);
     182      gtk_widget_show(errmsg_full(NULL, (errfunc_t)gtk_main_quit,
     183                                  NULL, "%s", err));
    182184      g_free(err);
    183185    }
    184186  } else {
    185     errmsg_full(NULL, (errfunc_t)gtk_main_quit, NULL, "%s", err);
     187    gtk_widget_show(errmsg_full(NULL, (errfunc_t)gtk_main_quit,
     188                                NULL, "%s", err));
    186189    g_free(err);
    187190  }
     
    190193
    191194  return 0;
    192 }
    193 
    194 void
    195 readargs(int argc, char **argv, int *port, int *limit) {
    196   char *name;
    197   int opt, num;
    198 
    199   *port = 0;
    200   *limit = 0;
    201 
    202   if(NULL == (name = strrchr(argv[0], '/')) || '\0' == *(++name))
    203     name = argv[0];
    204 
    205   for(num = 1; num < argc; num++)
    206     if(0 == strcmp(argv[num], "-help") || 0 == strcmp(argv[num], "--help"))
    207       goto usage;
    208 
    209   while(0 <= (opt = getopt(argc, argv, "hp:u:"))) {
    210     switch(opt) {
    211       case 'p':
    212         num = atoi(optarg);
    213         if(0 < num && 0xffff > num)
    214           *port = num;
    215         break;
    216       case 'u':
    217         num = atoi(optarg);
    218         if(0 != num)
    219           *limit = num;
    220         break;
    221       default:
    222         goto usage;
    223     }
    224   }
    225 
    226   return;
    227 
    228  usage:
    229   printf("usage: %s [-h] [-p port] [-u limit]\n", name);
    230   exit(1);
    231195}
    232196
     
    258222
    259223  data->tr = tr;
    260   data->wind = wind;
     224  data->wind = GTK_WINDOW(wind);
    261225  data->timer = -1;
    262226  /* filled in by makewind_list */
     
    278242  for(ii = g_list_first(saved); NULL != ii; ii = ii->next) {
    279243    ts = ii->data;
    280     addtorrent(tr, wind, ts->ts_torrent, ts->ts_directory, ts->ts_paused);
     244    addtorrent(tr, GTK_WINDOW(wind),
     245               ts->ts_torrent, ts->ts_directory, ts->ts_paused);
    281246    cf_freestate(ts);
    282247  }
     
    323288  fprintf(stderr, "quit: starting timeout at %i\n", edata->started);
    324289
    325   //exitcheck(edata);
    326 
    327290  /* returning FALSE means to destroy the window */
    328291  return TRUE;
     
    364327  data->timer = -1;
    365328
    366   gtk_widget_destroy(data->cbdata->wind);
     329  gtk_widget_destroy(GTK_WIDGET(data->cbdata->wind));
    367330  tr_close(data->cbdata->tr);
    368331  g_free(data->cbdata);
     
    382345  gtk_toolbar_set_style(GTK_TOOLBAR(bar), GTK_TOOLBAR_BOTH);
    383346
    384   for(ii = 0; ii < sizeof(actionitems) / sizeof(actionitems[0]); ii++) {
     347  for(ii = 0; ii < ALEN(actionitems); ii++) {
    385348    item = gtk_tool_button_new_from_stock(actionitems[ii].id);
    386349    gtk_tool_button_set_label(GTK_TOOL_BUTTON(item), actionitems[ii].name);
     
    420383  GtkCellRenderer *rendprog;
    421384
    422   assert(MC_ROW_COUNT == sizeof(types) / sizeof(types[0]));
     385  assert(MC_ROW_COUNT == ALEN(types));
    423386
    424387  model = gtk_list_store_newv(MC_ROW_COUNT, types);
     
    433396  g_object_set(rendprog, "text", "", NULL);
    434397
    435 /*
    436   col = gtk_tree_view_column_new_with_attributes(
    437     "Name", rend, "text", MC_NAME, NULL);
    438   gtk_tree_view_column_add_attribute(col, rend, "text", MC_SIZE);
    439   gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);
    440 
    441   col = gtk_tree_view_column_new_with_attributes(
    442     "Status", rend, "text", MC_STAT, NULL);
    443   gtk_tree_view_column_add_attribute(col, rend, "text", MC_ERR);
    444   gtk_tree_view_column_add_attribute(col, rend, "text", MC_DPEERS);
    445   gtk_tree_view_column_add_attribute(col, rend, "text", MC_UPEERS);
    446   gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);
    447 
    448   col = gtk_tree_view_column_new_with_attributes(
    449     "Progress", rendprog, "value", MC_PROG, NULL);
    450   gtk_tree_view_column_pack_start(col, rend, TRUE);
    451   gtk_tree_view_column_add_attribute(col, rend, "text", MC_ETA);
    452   gtk_tree_view_column_add_attribute(col, rend, "text", MC_DRATE);
    453   gtk_tree_view_column_add_attribute(col, rend, "text", MC_URATE);
    454   gtk_tree_view_column_add_attribute(col, rend, "text", MC_DOWN);
    455   gtk_tree_view_column_add_attribute(col, rend, "text", MC_UP);
    456   gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);
    457 */
    458 
    459398  gtk_tree_view_append_column(GTK_TREE_VIEW(view),
    460399    gtk_tree_view_column_new_with_attributes("Name", rend,
     
    490429    gtk_tree_view_column_new_with_attributes("Leechers", rend,
    491430                                             "text", MC_DPEERS, NULL));
    492   /*gtk_tree_view_append_column(GTK_TREE_VIEW(view),
    493     gtk_tree_view_column_new_with_attributes("", rend,
    494                                              "text", MC_PIECES, NULL));*/
    495431  gtk_tree_view_append_column(GTK_TREE_VIEW(view),
    496432    gtk_tree_view_column_new_with_attributes("Downloaded", rend,
     
    533469      MC_URATE, st[ii].rateUpload, MC_ETA, st[ii].eta, MC_PEERS, st[ii].peersTotal,
    534470      MC_UPEERS, st[ii].peersUploading, MC_DPEERS, st[ii].peersDownloading,
    535       /*MC_PIECES, st[ii].pieces,*/ MC_DOWN, st[ii].downloaded, MC_UP, st[ii].uploaded, -1);
     471      MC_DOWN, st[ii].downloaded, MC_UP, st[ii].uploaded, -1);
    536472  }
    537473  free(st);
     
    579515  /* XXX am I leaking references here? */
    580516  /* XXX can I cache this in cbdata? */
    581   for(ii = 0; ii < sizeof(actionitems) / sizeof(actionitems[0]); ii++) {
     517  for(ii = 0; ii < ALEN(actionitems); ii++) {
    582518    item = gtk_menu_item_new_with_label(actionitems[ii].name);
    583519    g_object_set_data(G_OBJECT(item), LIST_ACTION,
     
    611547  tr_stat_t *sb;
    612548
    613   if(ACT_OPEN == act) {
    614     makeaddwind(data);
    615     return;
     549  switch(act) {
     550    case ACT_OPEN:
     551      makeaddwind(data);
     552      return;
     553    case ACT_PREF:
     554      makeprefwindow(data->wind, data->tr);
     555      return;
     556    default:
     557      break;
    616558  }
    617559
     
    674616  g_signal_connect_swapped(GTK_FILE_SELECTION(wind)->cancel_button, "clicked",
    675617                           G_CALLBACK(gtk_widget_destroy), wind);
    676   gtk_window_set_transient_for(GTK_WINDOW(wind), GTK_WINDOW(data->wind));
     618  gtk_window_set_transient_for(GTK_WINDOW(wind), data->wind);
    677619  gtk_window_set_destroy_with_parent(GTK_WINDOW(wind), TRUE);
    678620  gtk_window_set_modal(GTK_WINDOW(wind), TRUE);
     
    681623
    682624gboolean
    683 addtorrent(tr_handle_t *tr, GtkWidget *parentwind, const char *torrent,
     625addtorrent(tr_handle_t *tr, GtkWindow *parentwind, const char *torrent,
    684626           const char *dir, gboolean paused) {
    685627  char *wd;
     628
     629  if(NULL == dir) {
     630    dir = cf_getpref(PREF_DIR);
     631    if(!mkdir_p(dir, 0777)) {
     632      errmsg(parentwind, "Failed to create download directory %s:\n%s",
     633             dir, strerror(errno));
     634      return FALSE;
     635    }
     636  }
    686637
    687638  if(0 != tr_torrentInit(tr, torrent)) {
     
    694645    tr_torrentSetFolder(tr, tr_torrentCount(tr) - 1, dir);
    695646  else {
    696     /* XXX need pref for download directory */
    697647    wd = g_new(char, MAXPATHLEN + 1);
    698648    if(NULL == getcwd(wd, MAXPATHLEN + 1))
     
    748698    assert(!"XXX i'm tired");
    749699  }
    750   wind = gtk_dialog_new_with_buttons(sb[index].info.name, GTK_WINDOW(data->wind),
     700  wind = gtk_dialog_new_with_buttons(sb[index].info.name, data->wind,
    751701    GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL);
    752702
     
    856806
    857807gboolean
    858 savetorrents(tr_handle_t *tr, GtkWidget *wind, int count, tr_stat_t *stat) {
     808savetorrents(tr_handle_t *tr, GtkWindow *wind, int count, tr_stat_t *stat) {
    859809  char *errstr;
    860810  tr_stat_t *st;
  • trunk/gtk/util.c

    r5 r7  
    2525*/
    2626
     27#include <sys/types.h>
     28#include <sys/stat.h>
     29#include <errno.h>
    2730#include <stdarg.h>
     31#include <string.h>
     32
    2833#include <gtk/gtk.h>
    2934
     
    3136
    3237static void
    33 errcb(GtkWidget *widget, int resp, gpointer data);
     38errcb(GtkWidget *wind, int resp, gpointer data);
    3439
    3540gboolean
     
    5156}
    5257
     58gboolean
     59mkdir_p(const char *name, mode_t mode) {
     60  struct stat sb;
     61  char *parent;
     62  gboolean ret;
     63  int oerrno;
     64
     65  if(0 != stat(name, &sb)) {
     66    if(ENOENT != errno)
     67      return FALSE;
     68    parent = g_path_get_dirname(name);
     69    ret = mkdir_p(parent, mode);
     70    oerrno = errno;
     71    g_free(parent);
     72    errno = oerrno;
     73    return (ret ? (0 == mkdir(name, mode)) : FALSE);
     74  }
     75
     76  if(!S_ISDIR(sb.st_mode)) {
     77    errno = ENOTDIR;
     78    return FALSE;
     79  }
     80
     81  return TRUE;
     82}
     83
    5384GtkWidget *
    54 errmsg(GtkWidget *wind, const char *format, ...) {
     85errmsg(GtkWindow *wind, const char *format, ...) {
    5586  GtkWidget *dialog;
    5687  va_list ap;
     
    6495
    6596GtkWidget *
    66 errmsg_full(GtkWidget *wind, errfunc_t func, void *data,
     97errmsg_full(GtkWindow *wind, errfunc_t func, void *data,
    6798            const char *format, ...) {
    6899  GtkWidget *dialog;
     
    77108
    78109GtkWidget *
    79 verrmsg(GtkWidget *wind, errfunc_t func, void *data,
     110verrmsg(GtkWindow *wind, errfunc_t func, void *data,
    80111        const char *format, va_list ap) {
    81112  GtkWidget *dialog;
     
    89120      NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s", msg);
    90121  else
    91     dialog = gtk_message_dialog_new(
    92       GTK_WINDOW(wind), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
     122    dialog = gtk_message_dialog_new(wind,
     123      GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
    93124      GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s", msg);
    94125
     
    99130  g_signal_connect(dialog, "response", G_CALLBACK(errcb), funcdata);
    100131  if(NULL != wind)
    101     gtk_widget_show_all(dialog);
     132    gtk_widget_show(dialog);
    102133  g_free(msg);
    103134
  • trunk/gtk/util.h

    r5 r7  
    2828#define TG_UTIL_H
    2929
     30#include <sys/types.h>
    3031#include <stdarg.h>
    3132
     
    3738#endif
    3839
     40/* return number of items in array */
     41#define ALEN(a)                 (sizeof(a) / sizeof((a)[0]))
     42
    3943gboolean
    4044strbool(const char *str);
     45
     46gboolean
     47mkdir_p(const char *name, mode_t mode);
    4148
    4249typedef void (*errfunc_t)(void*);
     
    4552
    4653GtkWidget *
    47 errmsg(GtkWidget *wind, const char *format, ...)
     54errmsg(GtkWindow *wind, const char *format, ...)
    4855#ifdef __GNUC__
    4956  __attribute__ ((format (printf, 2, 3)))
     
    5259
    5360GtkWidget *
    54 errmsg_full(GtkWidget *wind, errfunc_t func, void *data,
     61errmsg_full(GtkWindow *wind, errfunc_t func, void *data,
    5562            const char *format, ...)
    5663#ifdef __GNUC__
     
    6067
    6168GtkWidget *
    62 verrmsg(GtkWidget *wind, errfunc_t func, void *data,
     69verrmsg(GtkWindow *wind, errfunc_t func, void *data,
    6370        const char *format, va_list ap);
    6471
Note: See TracChangeset for help on using the changeset viewer.