code cleanup: let glib do more of the heavy lifting w.r.t. parsing command-line arguments, drag-and-drop strings

This commit is contained in:
Charles Kerr 2007-10-12 19:53:30 +00:00
parent ff36475fad
commit 2e6ebae16e
4 changed files with 130 additions and 245 deletions

View File

@ -69,36 +69,6 @@ struct dirdata
gboolean paused;
};
struct infowind
{
GtkWidget * widget;
TrTorrent * tor;
int64_t size;
GtkTreeModel * model;
GtkTreeRowReference * row;
GtkTreeModel * filesmodel;
guint timer;
struct
{
tr_tracker_info * track;
GtkLabel * trackwid;
GtkLabel * annwid;
GtkLabel * scrwid;
int seed;
GtkLabel * seedwid;
int leech;
GtkLabel * leechwid;
int done;
GtkLabel * donewid;
uint64_t up;
GtkLabel * upwid;
uint64_t down;
GtkLabel * downwid;
uint64_t left;
GtkLabel * leftwid;
} inf;
};
static void
addwindnocore( gpointer gdata, GObject * core );
static void

View File

@ -24,7 +24,6 @@
#include <sys/param.h>
#include <errno.h>
#include <getopt.h>
#include <signal.h>
#include <string.h>
#include <stdio.h>
@ -123,13 +122,9 @@ static GtkUIManager * myUIManager = NULL;
static sig_atomic_t global_sigcount = 0;
static GList *
readargs( int argc, char ** argv, gboolean * sendquit, gboolean * paused );
static gboolean
sendremote( GList * files, gboolean sendquit );
static void
gtksetup( int * argc, char *** argv, struct cbdata* );
static void
appsetup( TrWindow * wind, GList * args,
struct cbdata * , gboolean paused );
static void
@ -218,13 +213,32 @@ selectionChangedCB( GtkTreeSelection * s, gpointer unused UNUSED )
int
main( int argc, char ** argv )
{
char * err;
struct cbdata * cbdata = g_new (struct cbdata, 1);
char * err;
benc_val_t * state;
GList * argfiles;
gboolean didinit, didlock, sendquit, startpaused;
GList * argfiles;
gboolean didinit, didlock, sendquit, startpaused;
char * domain = "transmission";
GOptionEntry entries[] = {
{ "paused", 'p', 0, G_OPTION_ARG_NONE, &startpaused, _("Start with all torrents paused"), NULL },
{ "quit", 'q', 0, G_OPTION_ARG_NONE, &sendquit, _( "Request that the running instance quit"), NULL },
{ NULL, 0, 0, 0, NULL, NULL, NULL }
};
argfiles = readargs( argc, argv, &sendquit, &startpaused );
/* bind the gettext domain */
bindtextdomain( domain, TRANSMISSIONLOCALEDIR );
bind_textdomain_codeset( domain, "UTF-8" );
textdomain( domain );
g_set_application_name( _( "Transmission" ) );
/* initialize gtk */
gtk_init_with_args( &argc, &argv, _("[torrent files]"), entries, domain, NULL );
myUIManager = gtk_ui_manager_new ();
actions_init ( myUIManager, cbdata );
gtk_ui_manager_add_ui_from_string (myUIManager, fallback_ui_file, -1, NULL);
gtk_ui_manager_ensure_update (myUIManager);
gtk_window_set_default_icon_name ( "transmission-logo" );
argfiles = checkfilenames( argc-1, argv+1 );
didinit = cf_init( tr_getPrefsDirectory(), NULL );
didlock = FALSE;
if( didinit )
@ -233,12 +247,12 @@ main( int argc, char ** argv )
didlock = sendremote( argfiles, sendquit );
}
setupsighandlers(); /* set up handlers for fatal signals */
gtksetup( &argc, &argv, cbdata ); /* set up gtk and gettext */
if( ( didinit || cf_init( tr_getPrefsDirectory(), &err ) ) &&
( didlock || cf_lock( &err ) ) )
{
GtkWindow * mainwind;
GtkWindow * mainwind;
benc_val_t * state;
/* create main window now to be a parent to any error dialogs */
mainwind = GTK_WINDOW( tr_window_new( myUIManager ) );
@ -270,65 +284,6 @@ main( int argc, char ** argv )
return 0;
}
GList *
readargs( int argc, char ** argv, gboolean * sendquit, gboolean * startpaused )
{
struct option opts[] =
{
{ "help", no_argument, NULL, 'h' },
{ "paused", no_argument, NULL, 'p' },
{ "quit", no_argument, NULL, 'q' },
{ "version", no_argument, NULL, 'v' },
{ NULL, 0, NULL, 0 }
};
int opt;
const char * name;
*sendquit = FALSE;
*startpaused = FALSE;
gtk_parse_args( &argc, &argv );
name = g_get_prgname();
while( 0 <= ( opt = getopt_long( argc, argv, "hpqv", opts, NULL ) ) )
{
switch( opt )
{
case 'p':
*startpaused = TRUE;
break;
case 'q':
*sendquit = TRUE;
break;
case 'v':
case 'h':
printf(
_("usage: %s [-hpq] [files...]\n"
"\n"
"Transmission %s http://transmission.m0k.org/\n"
"A free, lightweight BitTorrent client with a simple, intuitive interface\n"
"\n"
" -h --help display this message and exit\n"
" -p --paused start with all torrents paused\n"
" -q --quit request that the running %s instance quit\n"
"\n"
"Only one instance of %s may run at one time. Multiple\n"
"torrent files may be loaded at startup by adding them to the command\n"
"line. If %s is already running, those torrents will be\n"
"opened in the running instance.\n"),
name, LONG_VERSION_STRING,
name, name, name );
exit(0);
break;
}
}
argc -= optind;
argv += optind;
return checkfilenames( argc, argv );
}
static gboolean
sendremote( GList * files, gboolean sendquit )
{
@ -358,36 +313,6 @@ sendremote( GList * files, gboolean sendquit )
return didlock;
}
static void
gtksetup( int * argc, char *** argv, struct cbdata * callback_data )
{
bindtextdomain( "transmission", TRANSMISSIONLOCALEDIR );
bind_textdomain_codeset( "transmission", "UTF-8" );
textdomain( "transmission" );
g_set_application_name( _("Transmission") );
gtk_init( argc, argv );
/* connect up the actions */
myUIManager = gtk_ui_manager_new ();
actions_init ( myUIManager, callback_data );
gtk_ui_manager_add_ui_from_string (myUIManager, fallback_ui_file, -1, NULL);
gtk_ui_manager_ensure_update (myUIManager);
/* tweak some style properties in dialogs to get closer to the GNOME HiG */
gtk_rc_parse_string(
"style \"transmission-standard\"\n"
"{\n"
" GtkDialog::action-area-border = 6\n"
" GtkDialog::button-spacing = 12\n"
" GtkDialog::content-area-border = 6\n"
"}\n"
"widget \"TransmissionDialog\" style \"transmission-standard\"\n" );
gtk_window_set_default_icon_name ( "transmission-logo" );
}
static void
appsetup( TrWindow * wind, GList * args,
struct cbdata * cbdata, gboolean paused )
@ -580,90 +505,91 @@ exitcheck( gpointer gdata )
}
static void
gotdrag(GtkWidget *widget SHUTUP, GdkDragContext *dc, gint x SHUTUP,
gint y SHUTUP, GtkSelectionData *sel, guint info SHUTUP, guint time,
gpointer gdata) {
struct cbdata *data = gdata;
char prefix[] = "file:";
char *files, *decoded, *deslashed, *hostless;
int ii, len;
GList *errs;
struct stat sb;
int prelen = strlen(prefix);
GList *paths, *freeables;
enum tr_torrent_action action;
gotdrag( GtkWidget * widget UNUSED,
GdkDragContext * dc,
gint x UNUSED,
gint y UNUSED,
GtkSelectionData * sel,
guint info UNUSED,
guint time,
gpointer gdata )
{
struct cbdata * data = gdata;
GList * paths = NULL;
GList * freeme = NULL;
#ifdef DND_DEBUG
char *sele = gdk_atom_name(sel->selection);
char *targ = gdk_atom_name(sel->target);
char *type = gdk_atom_name(sel->type);
char *sele = gdk_atom_name(sel->selection);
char *targ = gdk_atom_name(sel->target);
char *type = gdk_atom_name(sel->type);
fprintf(stderr, "dropped file: sel=%s targ=%s type=%s fmt=%i len=%i\n",
sele, targ, type, sel->format, sel->length);
g_free(sele);
g_free(targ);
g_free(type);
if(8 == sel->format) {
for(ii = 0; ii < sel->length; ii++)
fprintf(stderr, "%02X ", sel->data[ii]);
fprintf(stderr, "\n");
}
fprintf(stderr, "dropped file: sel=%s targ=%s type=%s fmt=%i len=%i\n",
sele, targ, type, sel->format, sel->length);
g_free(sele);
g_free(targ);
g_free(type);
if( sel->format == 8 ) {
for( i=0; i<sel->length; ++i )
fprintf(stderr, "%02X ", sel->data[i]);
fprintf(stderr, "\n");
}
#endif
errs = NULL;
paths = NULL;
freeables = NULL;
if(gdk_atom_intern("XdndSelection", FALSE) == sel->selection &&
8 == sel->format) {
/* split file list on carriage returns and linefeeds */
files = g_new(char, sel->length + 1);
memcpy(files, sel->data, sel->length);
files[sel->length] = '\0';
for(ii = 0; '\0' != files[ii]; ii++)
if('\015' == files[ii] || '\012' == files[ii])
files[ii] = '\0';
/* try to get a usable filename out of the URI supplied and add it */
for(ii = 0; ii < sel->length; ii += len + 1) {
if('\0' == files[ii])
len = 0;
else {
len = strlen(files + ii);
/* de-urlencode the URI */
decoded = urldecode(files + ii, len);
freeables = g_list_append(freeables, decoded);
if(g_utf8_validate(decoded, -1, NULL)) {
/* remove the file: prefix */
if(prelen < len && 0 == strncmp(prefix, decoded, prelen)) {
deslashed = decoded + prelen;
/* trim excess / characters from the beginning */
while('/' == deslashed[0] && '/' == deslashed[1])
deslashed++;
/* if the file doesn't exist, the first part might be a hostname */
if(0 > g_stat(deslashed, &sb) &&
NULL != (hostless = strchr(deslashed + 1, '/')) &&
0 == g_stat(hostless, &sb))
deslashed = hostless;
/* finally, add it to the list of torrents to try adding */
paths = g_list_append(paths, deslashed);
}
}
}
}
/* try to add any torrents we found */
if( NULL != paths )
if( ( sel->format == 8 ) &&
( sel->selection == gdk_atom_intern( "XdndSelection", FALSE ) ) )
{
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);
}
freestrlist(freeables);
g_free(files);
}
/* split file list on carriage returns and linefeeds */
int i;
char * str = g_strndup( (char*)sel->data, sel->length );
gchar ** files = g_strsplit_set( str, "\r\n", -1 );
for( i=0; files && files[i]; ++i )
{
char * filename;
if( !*files[i] ) /* empty filename... */
continue;
gtk_drag_finish(dc, (NULL != paths), FALSE, time);
/* decode the filename */
filename = urldecode( files[i], -1 );
freeme = g_list_prepend( freeme, filename );
if( !g_utf8_validate( filename, -1, NULL ) )
continue;
/* walk past "file://", if present */
if( g_str_has_prefix( filename, "file:" ) ) {
filename += 5;
while( g_str_has_prefix( filename, "//" ) )
++filename;
}
/* if the file doesn't exist, the first part
might be a hostname ... walk past it. */
if( !g_file_test( filename, G_FILE_TEST_EXISTS ) ) {
char * pch = strchr( filename + 1, '/' );
if( pch != NULL )
filename = pch;
}
/* finally, add it to the list of torrents to try adding */
if( g_file_test( filename, G_FILE_TEST_EXISTS ) )
paths = g_list_prepend( paths, filename );
}
/* try to add any torrents we found */
if( paths != NULL )
{
enum tr_torrent_action action = tr_prefs_get_action( PREF_KEY_ADDSTD );
paths = g_list_reverse( paths );
tr_core_add_list( data->core, paths, action, FALSE );
tr_core_torrents_added( data->core );
g_list_free( paths );
}
freestrlist( freeme );
g_strfreev( files );
g_free( str );
}
gtk_drag_finish(dc, (NULL != paths), FALSE, time);
}
static void
@ -893,7 +819,7 @@ about ( void )
gtk_about_dialog_set_wrap_license (a, TRUE);
#endif
gtk_about_dialog_set_logo_icon_name( a, "transmission-logo" );
gtk_about_dialog_set_comments( a, _("A simple yet powerful BitTorrent Client") );
gtk_about_dialog_set_comments( a, _("A fast and intuitive BitTorrent client") );
gtk_about_dialog_set_website( a, "http://transmission.m0k.org/" );
gtk_about_dialog_set_copyright( a, _("Copyright 2005-2007 The Transmission Project") );
gtk_about_dialog_set_authors( a, authors );

View File

@ -240,51 +240,38 @@ urldecode(const char *str, int len) {
}
GList *
checkfilenames(int argc, char **argv) {
char *pwd = g_get_current_dir();
int ii, cd;
char *dirstr, *filestr;
GList *ret = NULL;
checkfilenames( int argc, char **argv )
{
int i;
GList * ret = NULL;
char * pwd = g_get_current_dir( );
for(ii = 0; ii < argc; ii++) {
dirstr = g_path_get_dirname(argv[ii]);
if(!g_path_is_absolute(argv[ii])) {
filestr = g_build_filename(pwd, dirstr, NULL);
g_free(dirstr);
dirstr = filestr;
for( i=0; i<argc; ++i )
{
char * filename = g_path_is_absolute( argv[i] )
? g_strdup ( argv[i] )
: g_build_filename( pwd, argv[i], NULL );
if( g_file_test( filename, G_FILE_TEST_EXISTS ) )
ret = g_list_append( ret, filename );
else
g_free( filename );
}
cd = chdir(dirstr);
g_free(dirstr);
if(0 > cd)
continue;
dirstr = g_get_current_dir();
filestr = g_path_get_basename(argv[ii]);
ret = g_list_append(ret, g_build_filename(dirstr, filestr, NULL));
g_free(dirstr);
g_free(filestr);
}
chdir(pwd);
g_free(pwd);
return ret;
g_free( pwd );
return ret;
}
enum tr_torrent_action
toraddaction( const char * action )
{
if( NULL == action || 0 == strcmp( "copy", action ) )
{
if( !action || !strcmp( "copy", action ) )
return TR_TOR_COPY;
}
else if( 0 == strcmp( "move", action ) )
{
if( !strcmp( "move", action ) )
return TR_TOR_MOVE;
}
else
{
return TR_TOR_LEAVE;
}
return TR_TOR_LEAVE;
}
const char *
@ -294,8 +281,10 @@ toractionname( enum tr_torrent_action action )
{
case TR_TOR_COPY:
return "copy";
case TR_TOR_MOVE:
return "move";
default:
return "leave";
}

View File

@ -90,7 +90,7 @@ urldecode(const char *str, int len);
/* return a list of cleaned-up paths, with invalid directories removed */
GList *
checkfilenames(int argc, char **argv);
checkfilenames( int argc, char ** argv );
/* returns the flag for an action string */
enum tr_torrent_action