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:
parent
ff36475fad
commit
2e6ebae16e
|
@ -69,36 +69,6 @@ struct dirdata
|
||||||
gboolean paused;
|
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
|
static void
|
||||||
addwindnocore( gpointer gdata, GObject * core );
|
addwindnocore( gpointer gdata, GObject * core );
|
||||||
static void
|
static void
|
||||||
|
|
232
gtk/main.c
232
gtk/main.c
|
@ -24,7 +24,6 @@
|
||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <getopt.h>
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -123,13 +122,9 @@ static GtkUIManager * myUIManager = NULL;
|
||||||
|
|
||||||
static sig_atomic_t global_sigcount = 0;
|
static sig_atomic_t global_sigcount = 0;
|
||||||
|
|
||||||
static GList *
|
|
||||||
readargs( int argc, char ** argv, gboolean * sendquit, gboolean * paused );
|
|
||||||
static gboolean
|
static gboolean
|
||||||
sendremote( GList * files, gboolean sendquit );
|
sendremote( GList * files, gboolean sendquit );
|
||||||
static void
|
static void
|
||||||
gtksetup( int * argc, char *** argv, struct cbdata* );
|
|
||||||
static void
|
|
||||||
appsetup( TrWindow * wind, GList * args,
|
appsetup( TrWindow * wind, GList * args,
|
||||||
struct cbdata * , gboolean paused );
|
struct cbdata * , gboolean paused );
|
||||||
static void
|
static void
|
||||||
|
@ -218,13 +213,32 @@ selectionChangedCB( GtkTreeSelection * s, gpointer unused UNUSED )
|
||||||
int
|
int
|
||||||
main( int argc, char ** argv )
|
main( int argc, char ** argv )
|
||||||
{
|
{
|
||||||
struct cbdata * cbdata = g_new (struct cbdata, 1);
|
|
||||||
char * err;
|
char * err;
|
||||||
benc_val_t * state;
|
struct cbdata * cbdata = g_new (struct cbdata, 1);
|
||||||
GList * argfiles;
|
GList * argfiles;
|
||||||
gboolean didinit, didlock, sendquit, startpaused;
|
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 );
|
didinit = cf_init( tr_getPrefsDirectory(), NULL );
|
||||||
didlock = FALSE;
|
didlock = FALSE;
|
||||||
if( didinit )
|
if( didinit )
|
||||||
|
@ -233,12 +247,12 @@ main( int argc, char ** argv )
|
||||||
didlock = sendremote( argfiles, sendquit );
|
didlock = sendremote( argfiles, sendquit );
|
||||||
}
|
}
|
||||||
setupsighandlers(); /* set up handlers for fatal signals */
|
setupsighandlers(); /* set up handlers for fatal signals */
|
||||||
gtksetup( &argc, &argv, cbdata ); /* set up gtk and gettext */
|
|
||||||
|
|
||||||
if( ( didinit || cf_init( tr_getPrefsDirectory(), &err ) ) &&
|
if( ( didinit || cf_init( tr_getPrefsDirectory(), &err ) ) &&
|
||||||
( didlock || cf_lock( &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 */
|
/* create main window now to be a parent to any error dialogs */
|
||||||
mainwind = GTK_WINDOW( tr_window_new( myUIManager ) );
|
mainwind = GTK_WINDOW( tr_window_new( myUIManager ) );
|
||||||
|
@ -270,65 +284,6 @@ main( int argc, char ** argv )
|
||||||
return 0;
|
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
|
static gboolean
|
||||||
sendremote( GList * files, gboolean sendquit )
|
sendremote( GList * files, gboolean sendquit )
|
||||||
{
|
{
|
||||||
|
@ -358,36 +313,6 @@ sendremote( GList * files, gboolean sendquit )
|
||||||
return didlock;
|
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
|
static void
|
||||||
appsetup( TrWindow * wind, GList * args,
|
appsetup( TrWindow * wind, GList * args,
|
||||||
struct cbdata * cbdata, gboolean paused )
|
struct cbdata * cbdata, gboolean paused )
|
||||||
|
@ -580,18 +505,18 @@ exitcheck( gpointer gdata )
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gotdrag(GtkWidget *widget SHUTUP, GdkDragContext *dc, gint x SHUTUP,
|
gotdrag( GtkWidget * widget UNUSED,
|
||||||
gint y SHUTUP, GtkSelectionData *sel, guint info SHUTUP, guint time,
|
GdkDragContext * dc,
|
||||||
gpointer gdata) {
|
gint x UNUSED,
|
||||||
|
gint y UNUSED,
|
||||||
|
GtkSelectionData * sel,
|
||||||
|
guint info UNUSED,
|
||||||
|
guint time,
|
||||||
|
gpointer gdata )
|
||||||
|
{
|
||||||
struct cbdata * data = gdata;
|
struct cbdata * data = gdata;
|
||||||
char prefix[] = "file:";
|
GList * paths = NULL;
|
||||||
char *files, *decoded, *deslashed, *hostless;
|
GList * freeme = NULL;
|
||||||
int ii, len;
|
|
||||||
GList *errs;
|
|
||||||
struct stat sb;
|
|
||||||
int prelen = strlen(prefix);
|
|
||||||
GList *paths, *freeables;
|
|
||||||
enum tr_torrent_action action;
|
|
||||||
|
|
||||||
#ifdef DND_DEBUG
|
#ifdef DND_DEBUG
|
||||||
char *sele = gdk_atom_name(sel->selection);
|
char *sele = gdk_atom_name(sel->selection);
|
||||||
|
@ -603,64 +528,65 @@ gotdrag(GtkWidget *widget SHUTUP, GdkDragContext *dc, gint x SHUTUP,
|
||||||
g_free(sele);
|
g_free(sele);
|
||||||
g_free(targ);
|
g_free(targ);
|
||||||
g_free(type);
|
g_free(type);
|
||||||
if(8 == sel->format) {
|
if( sel->format == 8 ) {
|
||||||
for(ii = 0; ii < sel->length; ii++)
|
for( i=0; i<sel->length; ++i )
|
||||||
fprintf(stderr, "%02X ", sel->data[ii]);
|
fprintf(stderr, "%02X ", sel->data[i]);
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
errs = NULL;
|
if( ( sel->format == 8 ) &&
|
||||||
paths = NULL;
|
( sel->selection == gdk_atom_intern( "XdndSelection", FALSE ) ) )
|
||||||
freeables = NULL;
|
{
|
||||||
if(gdk_atom_intern("XdndSelection", FALSE) == sel->selection &&
|
|
||||||
8 == sel->format) {
|
|
||||||
/* split file list on carriage returns and linefeeds */
|
/* split file list on carriage returns and linefeeds */
|
||||||
files = g_new(char, sel->length + 1);
|
int i;
|
||||||
memcpy(files, sel->data, sel->length);
|
char * str = g_strndup( (char*)sel->data, sel->length );
|
||||||
files[sel->length] = '\0';
|
gchar ** files = g_strsplit_set( str, "\r\n", -1 );
|
||||||
for(ii = 0; '\0' != files[ii]; ii++)
|
for( i=0; files && files[i]; ++i )
|
||||||
if('\015' == files[ii] || '\012' == files[ii])
|
{
|
||||||
files[ii] = '\0';
|
char * filename;
|
||||||
|
if( !*files[i] ) /* empty filename... */
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
|
||||||
/* 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 */
|
/* finally, add it to the list of torrents to try adding */
|
||||||
paths = g_list_append(paths, deslashed);
|
if( g_file_test( filename, G_FILE_TEST_EXISTS ) )
|
||||||
}
|
paths = g_list_prepend( paths, filename );
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* try to add any torrents we found */
|
/* try to add any torrents we found */
|
||||||
if( NULL != paths )
|
if( paths != NULL )
|
||||||
{
|
{
|
||||||
action = tr_prefs_get_action( PREF_KEY_ADDSTD );
|
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_add_list( data->core, paths, action, FALSE );
|
||||||
tr_core_torrents_added( data->core );
|
tr_core_torrents_added( data->core );
|
||||||
g_list_free( paths );
|
g_list_free( paths );
|
||||||
}
|
}
|
||||||
freestrlist(freeables);
|
|
||||||
g_free(files);
|
freestrlist( freeme );
|
||||||
|
g_strfreev( files );
|
||||||
|
g_free( str );
|
||||||
}
|
}
|
||||||
|
|
||||||
gtk_drag_finish(dc, (NULL != paths), FALSE, time);
|
gtk_drag_finish(dc, (NULL != paths), FALSE, time);
|
||||||
|
@ -893,7 +819,7 @@ about ( void )
|
||||||
gtk_about_dialog_set_wrap_license (a, TRUE);
|
gtk_about_dialog_set_wrap_license (a, TRUE);
|
||||||
#endif
|
#endif
|
||||||
gtk_about_dialog_set_logo_icon_name( a, "transmission-logo" );
|
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_website( a, "http://transmission.m0k.org/" );
|
||||||
gtk_about_dialog_set_copyright( a, _("Copyright 2005-2007 The Transmission Project") );
|
gtk_about_dialog_set_copyright( a, _("Copyright 2005-2007 The Transmission Project") );
|
||||||
gtk_about_dialog_set_authors( a, authors );
|
gtk_about_dialog_set_authors( a, authors );
|
||||||
|
|
51
gtk/util.c
51
gtk/util.c
|
@ -240,52 +240,39 @@ urldecode(const char *str, int len) {
|
||||||
}
|
}
|
||||||
|
|
||||||
GList *
|
GList *
|
||||||
checkfilenames(int argc, char **argv) {
|
checkfilenames( int argc, char **argv )
|
||||||
char *pwd = g_get_current_dir();
|
{
|
||||||
int ii, cd;
|
int i;
|
||||||
char *dirstr, *filestr;
|
|
||||||
GList * ret = NULL;
|
GList * ret = NULL;
|
||||||
|
char * pwd = g_get_current_dir( );
|
||||||
|
|
||||||
for(ii = 0; ii < argc; ii++) {
|
for( i=0; i<argc; ++i )
|
||||||
dirstr = g_path_get_dirname(argv[ii]);
|
{
|
||||||
if(!g_path_is_absolute(argv[ii])) {
|
char * filename = g_path_is_absolute( argv[i] )
|
||||||
filestr = g_build_filename(pwd, dirstr, NULL);
|
? g_strdup ( argv[i] )
|
||||||
g_free(dirstr);
|
: g_build_filename( pwd, argv[i], NULL );
|
||||||
dirstr = filestr;
|
|
||||||
}
|
if( g_file_test( filename, G_FILE_TEST_EXISTS ) )
|
||||||
cd = chdir(dirstr);
|
ret = g_list_append( ret, filename );
|
||||||
g_free(dirstr);
|
else
|
||||||
if(0 > cd)
|
g_free( filename );
|
||||||
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 );
|
g_free( pwd );
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum tr_torrent_action
|
enum tr_torrent_action
|
||||||
toraddaction( const char * action )
|
toraddaction( const char * action )
|
||||||
{
|
{
|
||||||
if( NULL == action || 0 == strcmp( "copy", action ) )
|
if( !action || !strcmp( "copy", action ) )
|
||||||
{
|
|
||||||
return TR_TOR_COPY;
|
return TR_TOR_COPY;
|
||||||
}
|
|
||||||
else if( 0 == strcmp( "move", action ) )
|
if( !strcmp( "move", action ) )
|
||||||
{
|
|
||||||
return TR_TOR_MOVE;
|
return TR_TOR_MOVE;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return TR_TOR_LEAVE;
|
return TR_TOR_LEAVE;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
toractionname( enum tr_torrent_action action )
|
toractionname( enum tr_torrent_action action )
|
||||||
|
@ -294,8 +281,10 @@ toractionname( enum tr_torrent_action action )
|
||||||
{
|
{
|
||||||
case TR_TOR_COPY:
|
case TR_TOR_COPY:
|
||||||
return "copy";
|
return "copy";
|
||||||
|
|
||||||
case TR_TOR_MOVE:
|
case TR_TOR_MOVE:
|
||||||
return "move";
|
return "move";
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return "leave";
|
return "leave";
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue