preferences code refresh in the gtk+ client

This commit is contained in:
Charles Kerr 2007-09-27 20:57:58 +00:00
parent c81961d908
commit 713ded5ff4
13 changed files with 534 additions and 1404 deletions

View File

@ -36,6 +36,9 @@
#include <glib.h>
#include <glib/gi18n.h>
#include <libtransmission/transmission.h>
#include <libtransmission/bencode.h>
#include "conf.h"
#include "util.h"
@ -65,14 +68,11 @@ cf_benc_append(benc_val_t *val, char type, int incsize);
static void
cf_writebenc(const char *file, const char *tmp, benc_val_t *data,
char **errstr);
static gboolean
writefile_traverse(gpointer key, gpointer value, gpointer data);
static char *
getstateval(benc_val_t *state, char *line);
static char *gl_confdir = NULL;
static char *gl_old_confdir = NULL;
static GTree *gl_prefs = NULL;
static char *gl_lockpath = NULL;
static char *gl_old_lockpath = NULL;
@ -180,7 +180,7 @@ cf_readfile(const char *file, const char *oldfile, gsize *len,
gboolean *usedold, char **errstr) {
char *path;
GIOChannel *io;
GError *err;
GError *err = NULL;
char *ret;
*errstr = NULL;
@ -222,69 +222,112 @@ cf_readfile(const char *file, const char *oldfile, gsize *len,
return ret;
}
void
cf_loadprefs(char **errstr) {
char *data, *line, *eol, *sep, *key;
gsize len;
benc_val_t val;
gboolean usedold;
int ii;
/**
*** Prefs Files
**/
*errstr = NULL;
#define DEFAULT_GROUP "general"
if(NULL != gl_prefs)
g_tree_destroy(gl_prefs);
gl_prefs = g_tree_new_full((GCompareDataFunc)g_ascii_strcasecmp, NULL,
g_free, g_free);
data = cf_readfile(FILE_PREFS, OLD_FILE_PREFS, &len, &usedold, errstr);
if(NULL != *errstr) {
g_assert(NULL == data);
return;
}
if(NULL == data)
return;
memset(&val, 0, sizeof(val));
if(!usedold && !tr_bencLoad(data, len, &val, NULL)) {
if(TYPE_DICT == val.type) {
key = NULL;
for(ii = 0; ii < val.val.l.count; ii++) {
if(NULL == key) {
g_assert(TYPE_STR == val.val.l.vals[ii].type);
key = val.val.l.vals[ii].val.s.s;
} else {
if(TYPE_INT == val.val.l.vals[ii].type)
g_tree_insert(gl_prefs, g_strdup(key),
g_strdup_printf("%"PRIu64, val.val.l.vals[ii].val.i));
else if(TYPE_STR == val.val.l.vals[ii].type)
g_tree_insert(gl_prefs, g_strdup(key),
g_strdup(val.val.l.vals[ii].val.s.s));
key = NULL;
}
}
}
} else {
/* XXX remove this in a release or two */
for(line = data; NULL != (eol = strchr(line, PREF_SEP_LINE));
line = eol + 1) {
*eol = '\0';
if(g_utf8_validate(line, -1, NULL) &&
NULL != (sep = strchr(line, PREF_SEP_KEYVAL))) {
*sep = '\0';
g_tree_insert(gl_prefs, g_strcompress(line), g_strcompress(sep+1));
}
}
cf_saveprefs(errstr);
}
tr_bencFree(&val);
g_free(data);
static char*
getPrefsFilename( void )
{
return g_build_filename( tr_getPrefsDirectory(), "gtk", "prefs", NULL );
}
static GKeyFile*
getPrefsKeyFile( void )
{
static GKeyFile * myKeyFile = NULL;
if( myKeyFile == NULL )
{
char * filename = getPrefsFilename( );
myKeyFile = g_key_file_new( );
g_key_file_load_from_file( myKeyFile, filename, 0, NULL );
g_free( filename );
}
return myKeyFile;
}
int
pref_int_get( const char * key )
{
return g_key_file_get_integer( getPrefsKeyFile( ), DEFAULT_GROUP, key, NULL );
}
void
pref_int_set( const char * key, int value )
{
g_key_file_set_integer( getPrefsKeyFile( ), DEFAULT_GROUP, key, value );
}
void
pref_int_set_default( const char * key, int value )
{
if( !g_key_file_has_key( getPrefsKeyFile( ), DEFAULT_GROUP, key, NULL ) )
pref_int_set( key, value );
}
gboolean
pref_flag_get ( const char * key )
{
return g_key_file_get_boolean( getPrefsKeyFile( ), DEFAULT_GROUP, key, NULL );
}
void
pref_flag_set( const char * key, gboolean value )
{
g_key_file_set_boolean( getPrefsKeyFile( ), DEFAULT_GROUP, key, value );
}
void
pref_flag_set_default( const char * key, gboolean value )
{
if( !g_key_file_has_key( getPrefsKeyFile( ), DEFAULT_GROUP, key, NULL ) )
pref_flag_set( key, value );
}
char*
pref_string_get( const char * key )
{
return g_key_file_get_string( getPrefsKeyFile( ), DEFAULT_GROUP, key, NULL );
}
void
pref_string_set( const char * key, const char * value )
{
g_key_file_set_string( getPrefsKeyFile( ), DEFAULT_GROUP, key, value );
}
void
pref_string_set_default( const char * key, const char * value )
{
if( !g_key_file_has_key( getPrefsKeyFile( ), DEFAULT_GROUP, key, NULL ) )
pref_string_set( key, value );
}
void
pref_save(char **errstr)
{
GError * err = NULL;
gsize datalen;
char * data;
char * filename = getPrefsFilename( );
data = g_key_file_to_data( getPrefsKeyFile(), &datalen, &err );
if( !err ) {
GIOChannel * out = g_io_channel_new_file( filename, "w+", &err );
g_io_channel_write_chars( out, data, datalen, NULL, &err );
g_io_channel_unref( out );
}
if( errstr != NULL )
*errstr = err ? g_strdup( err->message ) : NULL;
g_free( filename );
g_free( data );
g_clear_error( &err );
}
/**
***
**/
benc_val_t *
cf_loadstate(char **errstr) {
char *data, *line, *eol, *prog;
@ -337,27 +380,13 @@ cf_benc_append(benc_val_t *val, char type, int incsize) {
val->val.l.vals[val->val.l.count-1].type = type;
}
const char *
cf_getpref(const char *name) {
g_assert(NULL != gl_prefs);
return g_tree_lookup(gl_prefs, name);
}
void
cf_setpref(const char *name, const char *value) {
g_assert(NULL != gl_prefs);
g_tree_insert(gl_prefs, g_strdup(name), g_strdup(value));
}
static void
cf_writebenc(const char *file, const char *tmp, benc_val_t *data,
char **errstr) {
char *path = g_build_filename(gl_confdir, file, NULL);
char *pathtmp = g_build_filename(gl_confdir, tmp, NULL);
GIOChannel *io = NULL;
GError *err;
GError *err = NULL;
char *datastr;
int len;
gsize written;
@ -402,45 +431,25 @@ cf_writebenc(const char *file, const char *tmp, benc_val_t *data,
free(datastr);
}
void
cf_saveprefs(char **errstr) {
benc_val_t val;
benc_val_t *ptr;
*errstr = NULL;
memset(&val, 0, sizeof(val));
val.type = TYPE_DICT;
val.val.l.alloc = val.val.l.count = g_tree_nnodes(gl_prefs) * 2;
val.val.l.vals = g_new0(benc_val_t, val.val.l.alloc);
ptr = val.val.l.vals;
g_tree_foreach(gl_prefs, writefile_traverse, &ptr);
g_assert(ptr - val.val.l.vals == val.val.l.alloc);
cf_writebenc(FILE_PREFS, FILE_PREFS_TMP, &val, errstr);
tr_bencFree(&val);
}
static gboolean
writefile_traverse(gpointer key, gpointer value, gpointer data) {
benc_val_t **ptr = data;
benc_val_t *bkey = *ptr;
benc_val_t *bval = (*ptr) + 1;
strbool( const char * str )
{
if( !str )
return FALSE;
*ptr = (*ptr) + 2;
bkey->type = TYPE_STR;
bkey->val.s.s = g_strdup(key);
bkey->val.s.i = strlen(key);
bval->type = TYPE_STR;
bval->val.s.s = g_strdup(value);
bval->val.s.i = strlen(value);
switch(str[0]) {
case 'y': case 't': case 'Y': case '1': case 'j': case 'e':
return TRUE;
default:
if(0 == g_ascii_strcasecmp("on", str))
return TRUE;
break;
}
return FALSE;
}
static char *
getstateval(benc_val_t *state, char *line) {
char *start, *end;

View File

@ -22,11 +22,32 @@
* DEALINGS IN THE SOFTWARE.
*****************************************************************************/
/**
***
**/
#ifndef TG_CONF_H
#define TG_CONF_H
#include <libtransmission/transmission.h>
#include <libtransmission/bencode.h>
int pref_int_get ( const char * key );
void pref_int_set ( const char * key, int value );
void pref_int_set_default ( const char * key, int default_value );
gboolean pref_flag_get ( const char * key );
void pref_flag_set ( const char * key, gboolean value );
void pref_flag_set_default ( const char * key, gboolean default_value );
char* pref_string_get ( const char * key );
void pref_string_set ( const char * key, const char * value );
void pref_string_set_default ( const char * key, const char * default_value );
void pref_save ( char **errstr );
/**
***
**/
struct benc_val_s;
gboolean
cf_init(const char *confdir, char **errstr);
@ -36,17 +57,11 @@ char *
cf_sockname(void);
void
cf_loadprefs(char **errstr);
const char *
cf_getpref(const char *name);
void
cf_setpref(const char *name, const char *value);
void
cf_saveprefs(char **errstr);
benc_val_t *
struct benc_val_s *
cf_loadstate(char **errstr);
void
cf_savestate(benc_val_t *state, char **errstr);
cf_savestate(struct benc_val_s *state, char **errstr);
void
cf_freestate(benc_val_t *state);
cf_freestate(struct benc_val_s *state);
#endif /* TG_CONF_H */

View File

@ -129,7 +129,7 @@ makeaddwind( GtkWindow * parent, TrCore * core )
GtkFileFilter *unfilter = gtk_file_filter_new();
GtkWidget *getdir = gtk_file_chooser_button_new(
_("Choose a download directory"), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
const char * pref;
char * pref;
data->widget = wind;
data->core = core;
@ -148,10 +148,10 @@ makeaddwind( GtkWindow * parent, TrCore * core )
gtk_box_pack_start_defaults(GTK_BOX(vbox), bbox);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(autocheck), TRUE);
pref = tr_prefs_get( PREF_ID_DIR );
if( NULL != pref )
{
pref = pref_string_get( PREF_KEY_DIR_DEFAULT );
if( pref != NULL ) {
gtk_file_chooser_set_current_folder( GTK_FILE_CHOOSER( wind ), pref );
g_free( pref );
}
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dircheck), FALSE);
@ -214,7 +214,8 @@ addresp(GtkWidget *widget, gint resp, gpointer gdata) {
if(data->usingaltdir)
dir = gtk_file_chooser_get_filename(data->altdir);
files = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(widget));
action = toraddaction( tr_prefs_get( PREF_ID_ADDSTD ) );
action = tr_prefs_get_action( PREF_KEY_ADDSTD );
if( NULL == dir )
{
stupidgtk = NULL;
@ -268,6 +269,7 @@ void
promptfordir( GtkWindow * parent, TrCore * core, GList * files, uint8_t * data,
size_t size, enum tr_torrent_action act, gboolean paused )
{
char * path;
struct dirdata * stuff;
GtkWidget * wind;
@ -295,8 +297,9 @@ promptfordir( GtkWindow * parent, TrCore * core, GList * files, uint8_t * data,
NULL );
gtk_file_chooser_set_local_only( GTK_FILE_CHOOSER( wind ), TRUE );
gtk_file_chooser_set_select_multiple( GTK_FILE_CHOOSER( wind ), FALSE );
gtk_file_chooser_set_filename( GTK_FILE_CHOOSER( wind ),
getdownloaddir() );
path = getdownloaddir( );
gtk_file_chooser_set_filename( GTK_FILE_CHOOSER( wind ), path );
g_free( path );
stuff->widget = wind;
@ -372,13 +375,10 @@ struct quitdata
static void
quitresp( GtkWidget * widget, int response, gpointer data )
{
struct quitdata * stuff;
gboolean doask;
struct quitdata * stuff = data;
stuff = data;
doask = !gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(stuff->dontask) );
tr_core_set_pref_bool( stuff->core, PREF_ID_ASKQUIT, doask );
pref_flag_set( PREF_KEY_ASKQUIT,
!gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(stuff->dontask) ) );
if( response == GTK_RESPONSE_ACCEPT )
stuff->func( stuff->cbdata );
@ -397,7 +397,7 @@ askquit( TrCore * core,
GtkWidget * wind;
GtkWidget * dontask;
if( !tr_prefs_get_bool_with_default( PREF_ID_ASKQUIT ) )
if( !pref_flag_get( PREF_KEY_ASKQUIT ) )
{
func( cbdata );
return;

View File

@ -590,7 +590,7 @@ smsg_add( enum ipc_msg id SHUTUP, benc_val_t * val, int64_t tag, void * arg )
return;
}
action = toraddaction( tr_prefs_get( PREF_ID_ADDIPC ) );
action = tr_prefs_get_action( PREF_KEY_ADDIPC );
for( ii = 0; ii < val->val.l.count; ii++ )
{
path = val->val.l.vals + ii;
@ -637,7 +637,7 @@ smsg_addone( enum ipc_msg id SHUTUP, benc_val_t * val, int64_t tag,
return;
}
action = toraddaction( tr_prefs_get( PREF_ID_ADDIPC ) );
action = tr_prefs_get_action( PREF_KEY_ADDIPC );
paused = ( NULL == start || start->val.i ? FALSE : TRUE );
if( NULL != file )
{
@ -997,33 +997,28 @@ smsg_pref( enum ipc_msg id, benc_val_t * val SHUTUP, int64_t tag, void * arg )
buf = ipc_mkint( con->ipc, &size, IPC_MSG_AUTOSTART, tag, 1 );
break;
case IPC_MSG_GETDIR:
pref = tr_prefs_get( PREF_ID_ASKDIR );
/* XXX sending back "" when we're prompting is kind of bogus */
pref = strbool( pref ) ? "" : getdownloaddir();
pref = pref_flag_get( PREF_KEY_DIR_ASK ) ? "" : getdownloaddir();
buf = ipc_mkstr( con->ipc, &size, IPC_MSG_DIR, tag, pref );
break;
case IPC_MSG_GETDOWNLIMIT:
num = -1;
if( tr_prefs_get_bool_with_default( PREF_ID_USEDOWNLIMIT ) )
{
num = tr_prefs_get_int_with_default( PREF_ID_DOWNLIMIT );
}
num = pref_flag_get( PREF_KEY_DL_LIMIT_ENABLED )
? pref_int_get( PREF_KEY_DL_LIMIT )
: -1;
buf = ipc_mkint( con->ipc, &size, IPC_MSG_DOWNLIMIT, tag, num );
break;
case IPC_MSG_GETPEX:
buf = ipc_mkint( con->ipc, &size, IPC_MSG_PEX, tag,
tr_prefs_get_bool_with_default( PREF_ID_PEX ) );
pref_flag_get( PREF_KEY_PEX ) );
break;
case IPC_MSG_GETPORT:
buf = ipc_mkint( con->ipc, &size, IPC_MSG_PORT, tag,
tr_prefs_get_int_with_default( PREF_ID_PORT ) );
pref_flag_get( PREF_KEY_PORT ) );
break;
case IPC_MSG_GETUPLIMIT:
num = -1;
if( tr_prefs_get_bool_with_default( PREF_ID_USEUPLIMIT ) )
{
num = tr_prefs_get_int_with_default( PREF_ID_UPLIMIT );
}
num = pref_flag_get( PREF_KEY_UL_LIMIT_ENABLED )
? pref_int_get( PREF_KEY_UL_LIMIT )
: -1;
buf = ipc_mkint( con->ipc, &size, IPC_MSG_UPLIMIT, tag, num );
break;
default:
@ -1052,7 +1047,7 @@ smsg_int( enum ipc_msg id, benc_val_t * val, int64_t tag, void * arg )
switch( id )
{
case IPC_MSG_AUTOMAP:
tr_core_set_pref_bool( srv->core, PREF_ID_NAT, val->val.i );
tr_core_set_pref_bool( srv->core, PREF_KEY_NAT, val->val.i );
break;
case IPC_MSG_AUTOSTART:
simpleresp( con, tag, IPC_MSG_BAD );
@ -1060,33 +1055,29 @@ smsg_int( enum ipc_msg id, benc_val_t * val, int64_t tag, void * arg )
case IPC_MSG_DOWNLIMIT:
if( 0 > val->val.i )
{
tr_core_set_pref_bool( srv->core, PREF_ID_USEDOWNLIMIT,
FALSE );
tr_core_set_pref_bool( srv->core, PREF_KEY_DL_LIMIT_ENABLED, 0 );
}
else
{
tr_core_set_pref_int( srv->core, PREF_ID_DOWNLIMIT,
val->val.i );
tr_core_set_pref_bool( srv->core, PREF_ID_USEDOWNLIMIT, TRUE );
tr_core_set_pref_int( srv->core, PREF_KEY_DL_LIMIT, val->val.i );
tr_core_set_pref_bool( srv->core, PREF_KEY_DL_LIMIT_ENABLED, 1 );
}
break;
case IPC_MSG_PEX:
tr_core_set_pref_bool( srv->core, PREF_ID_PEX, val->val.i );
tr_core_set_pref_bool( srv->core, PREF_KEY_PEX, val->val.i );
break;
case IPC_MSG_PORT:
tr_core_set_pref_int( srv->core, PREF_ID_PORT, val->val.i );
tr_core_set_pref_int( srv->core, PREF_KEY_PORT, val->val.i );
break;
case IPC_MSG_UPLIMIT:
if( 0 > val->val.i )
{
tr_core_set_pref_bool( srv->core, PREF_ID_USEUPLIMIT,
FALSE );
tr_core_set_pref_bool( srv->core, PREF_KEY_UL_LIMIT_ENABLED, 0 );
}
else
{
tr_core_set_pref_int( srv->core, PREF_ID_UPLIMIT,
val->val.i );
tr_core_set_pref_bool( srv->core, PREF_ID_USEUPLIMIT, TRUE );
tr_core_set_pref_int( srv->core, PREF_KEY_UL_LIMIT, val->val.i );
tr_core_set_pref_bool( srv->core, PREF_KEY_UL_LIMIT_ENABLED, 1 );
}
break;
default:
@ -1110,7 +1101,7 @@ smsg_str( enum ipc_msg id, benc_val_t * val, int64_t tag, void * arg )
switch( id )
{
case IPC_MSG_DIR:
tr_core_set_pref( srv->core, PREF_ID_DIR, val->val.s.s );
tr_core_set_pref( srv->core, PREF_KEY_DIR_DEFAULT, val->val.s.s );
break;
default:
g_assert_not_reached();

View File

@ -105,7 +105,7 @@ struct cbdata {
TrCore * core;
GtkWidget * icon;
GtkWidget * msgwin;
TrPrefs * prefs;
GtkWidget * prefs;
guint timer;
gboolean closing;
GList * errqueue;
@ -156,7 +156,7 @@ corepromptdata( TrCore *, uint8_t *, size_t, gboolean, gpointer );
static void
readinitialprefs( struct cbdata * cbdata );
static void
prefschanged( TrCore * core, int id, gpointer data );
prefschanged( TrCore * core, const char * key, gpointer data );
static void
setpex( tr_torrent * tor, void * arg );
static gboolean
@ -244,12 +244,7 @@ main( int argc, char ** argv )
mainwind = GTK_WINDOW( tr_window_new( myUIManager ) );
/* try to load prefs and saved state */
cf_loadprefs( &err );
if( NULL != err )
{
errmsg( mainwind, "%s", err );
g_free( err );
}
tr_prefs_init_global( );
state = cf_loadstate( &err );
if( NULL != err )
{
@ -428,7 +423,7 @@ appsetup( TrWindow * wind, GList * args,
if( NULL != args )
{
action = toraddaction( tr_prefs_get( PREF_ID_ADDIPC ) );
action = tr_prefs_get_action( PREF_KEY_ADDIPC );
tr_core_add_list( cbdata->core, args, action, paused );
}
tr_core_torrents_added( cbdata->core );
@ -659,7 +654,7 @@ gotdrag(GtkWidget *widget SHUTUP, GdkDragContext *dc, gint x SHUTUP,
/* try to add any torrents we found */
if( NULL != paths )
{
action = toraddaction( tr_prefs_get( PREF_ID_ADDSTD ) );
action = tr_prefs_get_action( PREF_KEY_ADDSTD );
tr_core_add_list( data->core, paths, action, FALSE );
tr_core_torrents_added( data->core );
g_list_free(paths);
@ -742,87 +737,72 @@ corepromptdata( TrCore * core, uint8_t * data, size_t size,
static void
readinitialprefs( struct cbdata * cbdata )
{
int prefs[] =
size_t i;
const char * keys[] =
{
PREF_ID_PORT,
PREF_ID_DOWNLIMIT,
PREF_ID_USEDOWNLIMIT,
PREF_ID_UPLIMIT,
PREF_ID_USEUPLIMIT,
PREF_ID_NAT,
PREF_ID_ICON,
PREF_ID_PEX,
PREF_KEY_PORT,
PREF_KEY_DL_LIMIT_ENABLED,
PREF_KEY_DL_LIMIT,
PREF_KEY_UL_LIMIT_ENABLED,
PREF_KEY_UL_LIMIT,
PREF_KEY_NAT,
PREF_KEY_PEX,
PREF_KEY_SYSTRAY
};
int ii;
for( ii = 0; ALEN( prefs ) > ii; ii++ )
{
prefschanged( NULL, prefs[ii], cbdata );
}
for( i=0; i<G_N_ELEMENTS(keys); ++i )
prefschanged( NULL, keys[i], cbdata );
}
static void
prefschanged( TrCore * core SHUTUP, int id, gpointer data )
prefschanged( TrCore * core UNUSED, const char * key, gpointer data )
{
struct cbdata * cbdata = data;
tr_handle * tr = tr_core_handle( cbdata->core );
gboolean boolval;
switch( id )
if( !strcmp( key, PREF_KEY_PORT ) )
{
case PREF_ID_PORT:
tr_setBindPort( tr, tr_prefs_get_int_with_default( id ) );
break;
case PREF_ID_USEDOWNLIMIT:
tr_setUseGlobalSpeedLimit( tr, TR_DOWN,
tr_prefs_get_bool_with_default( PREF_ID_USEDOWNLIMIT ) );
break;
case PREF_ID_DOWNLIMIT:
tr_setGlobalSpeedLimit( tr, TR_DOWN,
tr_prefs_get_int_with_default( PREF_ID_DOWNLIMIT ) );
break;
case PREF_ID_USEUPLIMIT:
tr_setUseGlobalSpeedLimit( tr, TR_UP,
tr_prefs_get_bool_with_default( PREF_ID_USEUPLIMIT ) );
break;
case PREF_ID_UPLIMIT:
tr_setGlobalSpeedLimit( tr, TR_UP,
tr_prefs_get_int_with_default( PREF_ID_UPLIMIT ) );
break;
case PREF_ID_NAT:
tr_natTraversalEnable( tr, tr_prefs_get_bool_with_default( id ) );
break;
case PREF_ID_ICON:
if( tr_prefs_get_bool_with_default( id ) )
{
makeicon( cbdata );
}
else if( NULL != cbdata->icon )
{
g_message ("foo");
g_object_unref( cbdata->icon );
cbdata->icon = NULL;
}
break;
case PREF_ID_PEX:
boolval = tr_prefs_get_bool_with_default( id );
tr_torrentIterate( tr, setpex, &boolval );
break;
case PREF_ID_DIR:
case PREF_ID_ASKDIR:
case PREF_ID_ADDSTD:
case PREF_ID_ADDIPC:
case PREF_ID_MSGLEVEL:
case PREF_MAX_ID:
break;
const int port = pref_int_get( key );
tr_setBindPort( tr, port );
}
else if( !strcmp( key, PREF_KEY_DL_LIMIT_ENABLED ) )
{
const gboolean b = pref_flag_get( key );
tr_setUseGlobalSpeedLimit( tr, TR_DOWN, b );
}
else if( !strcmp( key, PREF_KEY_DL_LIMIT ) )
{
const int limit = pref_int_get( key );
tr_setGlobalSpeedLimit( tr, TR_DOWN, limit );
}
else if( !strcmp( key, PREF_KEY_UL_LIMIT_ENABLED ) )
{
const gboolean b = pref_flag_get( key );
tr_setUseGlobalSpeedLimit( tr, TR_UP, b );
}
else if( !strcmp( key, PREF_KEY_UL_LIMIT ) )
{
const int limit = pref_int_get( key );
tr_setGlobalSpeedLimit( tr, TR_UP, limit );
}
else if( !strcmp( key, PREF_KEY_NAT ) )
{
const gboolean enabled = pref_flag_get( key );
tr_natTraversalEnable( tr, enabled );
}
else if( !strcmp( key, PREF_KEY_SYSTRAY ) )
{
if( pref_flag_get( key ) ) {
makeicon( cbdata );
} else if( cbdata->icon ) {
g_object_unref( cbdata->icon );
cbdata->icon = NULL;
}
}
else if( !strcmp( key, PREF_KEY_PEX ) )
{
gboolean enabled = pref_flag_get( key );
tr_torrentIterate( tr, setpex, &enabled );
}
}
@ -1064,8 +1044,7 @@ doAction ( const char * action_name, gpointer user_data )
{
if( NULL == data->prefs )
{
data->prefs = tr_prefs_new_with_parent( G_OBJECT( data->core ),
data->wind );
data->prefs = tr_prefs_dialog_new( G_OBJECT(data->core), data->wind );
g_signal_connect( data->prefs, "destroy",
G_CALLBACK( gtk_widget_destroyed ), &data->prefs );
gtk_widget_show( GTK_WIDGET( data->prefs ) );

View File

@ -141,7 +141,7 @@ level_combo_changed_cb( GtkWidget * w, TrCore * core )
GtkTreeModel * m = gtk_combo_box_get_model( GTK_COMBO_BOX(w) );
gtk_tree_model_get( m, &iter, 1, &id, -1 );
tr_setMessageLevel( id );
tr_core_set_pref_int( core, PREF_ID_MSGLEVEL, id );
tr_core_set_pref_int( core, PREF_KEY_MSGLEVEL, id );
msgwin_update( );
}
}
@ -259,8 +259,7 @@ msgwin_create( TrCore * core )
store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT);
curlevel = TR_MSG_INF;
tr_prefs_get_int( PREF_ID_MSGLEVEL, &curlevel );
curlevel = pref_int_get( PREF_KEY_MSGLEVEL );
for( i=ii=0; i<G_N_ELEMENTS(trLevels); ++i ) {
GtkTreeIter iter;
gtk_list_store_append (store, &iter);
@ -309,9 +308,7 @@ msgwin_create( TrCore * core )
void
msgwin_loadpref( void )
{
int level = TR_MSG_INF;
textbuf = debug_window_text_buffer_new ( );
tr_prefs_get_int( PREF_ID_MSGLEVEL, &level );
tr_setMessageLevel( level );
tr_setMessageLevel( pref_int_get( PREF_KEY_MSGLEVEL ) );
tr_setMessageQueuing( TRUE );
}

View File

@ -118,8 +118,8 @@ tr_core_class_init( gpointer g_class, gpointer g_class_data SHUTUP )
core_class->prefsig = g_signal_new( "prefs-changed",
G_TYPE_FROM_CLASS( g_class ),
G_SIGNAL_RUN_LAST, 0, NULL, NULL,
g_cclosure_marshal_VOID__INT,
G_TYPE_NONE, 1, G_TYPE_INT );
g_cclosure_marshal_VOID__STRING,
G_TYPE_NONE, 1, G_TYPE_STRING );
}
void
@ -252,6 +252,8 @@ tr_core_dispose( GObject * obj )
}
self->disposed = TRUE;
pref_save( NULL );
#ifdef REFDBG
fprintf( stderr, "core %p dispose\n", self );
#endif
@ -408,21 +410,22 @@ tr_core_load( TrCore * self, gboolean forcepaused )
int flags;
int count = 0;
tr_torrent ** torrents;
const char * destination;
char * path;
TR_IS_CORE( self );
destination = getdownloaddir( );
path = getdownloaddir( );
flags = 0;
if( forcepaused )
flags |= TR_FLAG_PAUSED;
torrents = tr_loadTorrents ( self->handle, destination, flags, &count );
torrents = tr_loadTorrents ( self->handle, path, flags, &count );
for( i=0; i<count; ++i )
tr_core_insert( self, tr_torrent_new_preexisting( torrents[i] ) );
tr_free( torrents );
g_free( path );
return count;
}
@ -470,43 +473,46 @@ int
tr_core_add_list( TrCore * self, GList * paths, enum tr_torrent_action act,
gboolean paused )
{
const char * pref = tr_prefs_get( PREF_ID_ASKDIR );
TrCoreClass * class;
int count;
char * dir;
int count;
TR_IS_CORE( self );
if( strbool( pref ) )
if( pref_flag_get( PREF_KEY_DIR_ASK ) )
{
class = g_type_class_peek( TR_CORE_TYPE );
TrCoreClass * class = g_type_class_peek( TR_CORE_TYPE );
g_signal_emit( self, class->promptsig, 0, paths, act, paused );
return 0;
}
pref = getdownloaddir();
dir = getdownloaddir();
count = 0;
for( ; paths; paths=paths->next )
if( tr_core_add_dir( self, paths->data, pref, act, paused ) )
if( tr_core_add_dir( self, paths->data, dir, act, paused ) )
count++;
g_free( dir );
return count;
}
gboolean
tr_core_add_data( TrCore * self, uint8_t * data, size_t size, gboolean paused )
{
const char * pref = tr_prefs_get( PREF_ID_ASKDIR );
gboolean ret;
char * path;
TR_IS_CORE( self );
if( strbool( pref ) )
if( pref_flag_get( PREF_KEY_DIR_ASK ) )
{
TrCoreClass * class = g_type_class_peek( TR_CORE_TYPE );
g_signal_emit( self, class->promptdatasig, 0, data, size, paused );
return FALSE;
}
return tr_core_add_data_dir( self, data, size, getdownloaddir(), paused );
path = getdownloaddir( );
ret = tr_core_add_data_dir( self, data, size, path, paused );
g_free( path );
return ret;
}
gboolean
@ -637,48 +643,48 @@ tr_core_quit( TrCore * self )
g_signal_emit( self, class->quitsig, 0 );
}
void
tr_core_set_pref( TrCore * self, int id, const char * val )
/**
*** Prefs
**/
static void
commitPrefsChange( TrCore * self, const char * key )
{
const char * name, * old;
char * errstr;
TrCoreClass * class;
TrCoreClass * class = g_type_class_peek( TR_CORE_TYPE );
pref_save( NULL );
g_signal_emit( self, class->prefsig, 0, key );
}
TR_IS_CORE( self );
/* don't change anything if the new value is the same as the old one */
name = tr_prefs_name( id );
old = cf_getpref( name );
if( !tr_strcmp( old, val ) )
return;
cf_setpref( name, val );
/* write prefs to disk */
cf_saveprefs( &errstr );
if( NULL != errstr )
void
tr_core_set_pref( TrCore * self, const char * key, const char * newval )
{
char * oldval = pref_string_get( key );
if( tr_strcmp( oldval, newval ) )
{
tr_core_errsig( self, TR_CORE_ERR_SAVE_STATE, errstr );
g_free( errstr );
pref_string_set( key, newval );
commitPrefsChange( self, key );
}
/* signal a pref change */
class = g_type_class_peek( TR_CORE_TYPE );
g_signal_emit( self, class->prefsig, 0, id );
g_free( oldval );
}
void
tr_core_set_pref_bool( TrCore * self, int id, gboolean val )
tr_core_set_pref_bool( TrCore * self, const char * key, gboolean newval )
{
tr_core_set_pref( self, id, ( val ? "yes" : "no" ) );
const gboolean oldval = pref_flag_get( key );
if( oldval != newval )
{
pref_flag_set( key, newval );
commitPrefsChange( self, key );
}
}
void
tr_core_set_pref_int( TrCore * self, int id, int val )
tr_core_set_pref_int( TrCore * self, const char * key, int newval )
{
char buf[32];
g_snprintf( buf, sizeof buf, "%i", val );
tr_core_set_pref( self, id, buf );
const int oldval = pref_int_get( key );
if( oldval != newval )
{
pref_int_set( key, newval );
commitPrefsChange( self, key );
}
}

View File

@ -172,17 +172,17 @@ tr_core_quit( TrCore * self );
/* Set a preference value, save the prefs file, and emit the
"prefs-changed" signal */
void
tr_core_set_pref( TrCore * self, int id, const char * val );
tr_core_set_pref( TrCore * self, const char * key, const char * val );
/* Set a boolean preference value, save the prefs file, and emit the
"prefs-changed" signal */
void
tr_core_set_pref_bool( TrCore * self, int id, gboolean val );
tr_core_set_pref_bool( TrCore * self, const char * key, gboolean val );
/* Set an integer preference value, save the prefs file, and emit the
"prefs-changed" signal */
void
tr_core_set_pref_int( TrCore * self, int id, int val );
tr_core_set_pref_int( TrCore * self, const char * key, int val );
/* column names for the model used to store torrent information */
/* keep this in sync with the type array in tr_core_init() in tr_core.c */

File diff suppressed because it is too large Load Diff

View File

@ -1,116 +1,40 @@
/******************************************************************************
* $Id$
/*
* This file Copyright (C) 2007 Charles Kerr <charles@rebelbase.com>
*
* Copyright (c) 2007 Transmission authors and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*****************************************************************************/
* This file is licensed by the GPL version 2. Works owned by the
* Transmission project are granted a special exemption to clause 2(b)
* so that the bulk of its code can remain under the MIT license.
* This exemption does not extend to derived works not owned by
* the Transmission project.
*
* $Id:$
*/
#ifndef TR_PREFS_H
#define TR_PREFS_H
#include <gtk/gtk.h>
#include "conf.h"
GtkWidget * tr_prefs_dialog_new( GObject * core, GtkWindow * parent );
#define TR_PREFS_TYPE ( tr_prefs_get_type() )
#define PREF_KEY_DL_LIMIT_ENABLED "download-limit-enabled"
#define PREF_KEY_DL_LIMIT "download-limit"
#define PREF_KEY_UL_LIMIT_ENABLED "upload-limit-enabled"
#define PREF_KEY_UL_LIMIT "upload-limit"
#define PREF_KEY_DIR_ASK "prompt-for-download-directory"
#define PREF_KEY_DIR_DEFAULT "default-download-directory"
#define PREF_KEY_ADDSTD "add-behavior-standard"
#define PREF_KEY_ADDIPC "add-behavior-ipc"
#define PREF_KEY_PORT "listening-port"
#define PREF_KEY_NAT "nat-traversal-enabled"
#define PREF_KEY_PEX "pex-enabled"
#define PREF_KEY_SYSTRAY "system-tray-icon-enabled"
#define PREF_KEY_ASKQUIT "prompt-before-exit"
#define PREF_KEY_MSGLEVEL "debug-message-level"
#define TR_PREFS( obj ) \
( G_TYPE_CHECK_INSTANCE_CAST( (obj), TR_PREFS_TYPE, TrPrefs ) )
void tr_prefs_init_global( void );
#define TR_PREFS_CLASS( class ) \
( G_TYPE_CHECK_CLASS_CAST( (class), TR_PREFS_TYPE, TrPrefsClass ) )
#define TR_IS_PREFS( obj ) \
( G_TYPE_CHECK_INSTANCE_TYPE( (obj), TR_PREFS_TYPE ) )
#define TR_IS_PREFS_CLASS( class ) \
( G_TYPE_CHECK_CLASS_TYPE( (class), TR_PREFS_TYPE ) )
#define TR_PREFS_GET_CLASS( obj ) \
( G_TYPE_INSTANCE_GET_CLASS( (obj), TR_PREFS_TYPE, TrPrefsClass ) )
typedef struct _TrPrefs TrPrefs;
typedef struct _TrPrefsClass TrPrefsClass;
/* treat the contents of this structure as private */
struct _TrPrefs
{
GtkDialog parent;
GtkTreeModel * combomodel;
GObject * core;
gulong sigid;
GtkWidget ** prefwids;
gboolean fileselhack;
gboolean disposed;
};
struct _TrPrefsClass
{
GtkDialogClass parent;
};
GType
tr_prefs_get_type( void );
TrPrefs *
tr_prefs_new( GObject * core );
TrPrefs *
tr_prefs_new_with_parent( GObject * core, GtkWindow * parent );
/* please keep this in sync with defs in tr_prefs.c */
enum
{
PREF_ID_USEDOWNLIMIT = 0,
PREF_ID_DOWNLIMIT,
PREF_ID_USEUPLIMIT,
PREF_ID_UPLIMIT,
PREF_ID_ASKDIR,
PREF_ID_DIR,
PREF_ID_PORT,
PREF_ID_NAT,
PREF_ID_PEX,
PREF_ID_ICON,
PREF_ID_ASKQUIT,
PREF_ID_ADDSTD,
PREF_ID_ADDIPC,
PREF_ID_MSGLEVEL,
PREF_MAX_ID
};
const char *
tr_prefs_name( int id );
/* convenience macros and functions for reading pref by id */
#define tr_prefs_get( id ) cf_getpref( tr_prefs_name( (id) ) )
gboolean
tr_prefs_get_int( int id, int * val );
gboolean
tr_prefs_get_bool( int id, gboolean * val );
int
tr_prefs_get_int_with_default( int id );
gboolean
tr_prefs_get_bool_with_default( int id );
int tr_prefs_get_action( const char * key );
void tr_prefs_set_action( const char * key, int action );
#endif

View File

@ -33,6 +33,7 @@
#include "tr_prefs.h"
#include "tr_torrent.h"
#include "conf.h"
#include "util.h"
enum {
@ -283,8 +284,7 @@ tr_torrent_stop( TrTorrent * self )
static TrTorrent *
maketorrent( tr_torrent * handle )
{
tr_torrentDisablePex( handle,
!tr_prefs_get_bool_with_default( PREF_ID_PEX ) );
tr_torrentDisablePex( handle, !pref_flag_get( PREF_KEY_PEX ) );
return g_object_new( TR_TORRENT_TYPE,
"torrent-handle", handle,

View File

@ -35,6 +35,7 @@
#include "tr_prefs.h"
#include "tr_torrent.h"
#include "conf.h"
#include "util.h"
#define BESTDECIMAL(d) (10.0 > (d) ? 2 : (100.0 > (d) ? 1 : 0))
@ -51,28 +52,6 @@ tr_strcmp( const char * a, const char * b )
return 0;
}
gboolean
strbool( const char * str )
{
if( !str )
return FALSE;
switch(str[0]) {
case 'y':
case 'Y':
case '1':
case 'j':
case 'e':
return TRUE;
default:
if(0 == g_ascii_strcasecmp("on", str))
return TRUE;
break;
}
return FALSE;
}
static const char *sizestrs[] = {
N_("B"), N_("KiB"), N_("MiB"), N_("GiB"), N_("TiB"), N_("PiB"), N_("EiB"),
};
@ -314,15 +293,15 @@ toractionname( enum tr_torrent_action action )
}
}
const char *
char *
getdownloaddir( void )
{
static char * wd = NULL;
const char * dir = tr_prefs_get( PREF_ID_DIR );
if (NULL == dir) {
if (NULL == wd)
wd = g_get_current_dir();
dir = wd;
char * dir = pref_string_get( PREF_KEY_DIR_DEFAULT );
if ( dir == NULL ) {
if( wd == NULL )
wd = g_get_current_dir();
dir = g_strdup( wd );
}
return dir;
}

View File

@ -44,11 +44,6 @@ enum tr_torrent_action { TR_TOR_LEAVE, TR_TOR_COPY, TR_TOR_MOVE };
/* used for a callback function with a data parameter */
typedef void (*callbackfunc_t)(void*);
/* try to interpret a string as a textual representation of a boolean */
/* note that this isn't localized */
gboolean
strbool(const char *str);
/* return a human-readable string for the size given in bytes.
the string must be g_free()d */
char *
@ -106,7 +101,7 @@ const char *
toractionname( enum tr_torrent_action action );
/* retrieve the global download directory */
const char *
char *
getdownloaddir( void );
#ifdef GTK_MAJOR_VERSION