(gtk) new "add torrent" popup to let users choose which files to download, file priority, add paused, delete source .torrent, etc
This commit is contained in:
parent
e581d5228e
commit
85c49dbbee
|
@ -23,6 +23,7 @@ noinst_HEADERS = \
|
|||
logo.h \
|
||||
makemeta-ui.h \
|
||||
msgwin.h \
|
||||
open.h \
|
||||
stats.h \
|
||||
sexy-icon-entry.h \
|
||||
torrent-cell-renderer.h \
|
||||
|
@ -48,6 +49,7 @@ transmission_SOURCES = \
|
|||
main.c \
|
||||
makemeta-ui.c \
|
||||
msgwin.c \
|
||||
open.c \
|
||||
sexy-icon-entry.c \
|
||||
stats.c \
|
||||
torrent-cell-renderer.c \
|
||||
|
|
313
gtk/dialogs.c
313
gtk/dialogs.c
|
@ -22,11 +22,6 @@
|
|||
* DEALINGS IN THE SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
|
@ -36,186 +31,62 @@
|
|||
#include "dialogs.h"
|
||||
#include "hig.h"
|
||||
#include "tr_core.h"
|
||||
#include "tr_icon.h"
|
||||
#include "tr_prefs.h"
|
||||
#include "util.h"
|
||||
|
||||
#define UPDATE_INTERVAL 1000
|
||||
#define PREFNAME "transmission-dialog-pref-name"
|
||||
#define FILESWIND_EXTRA_INDENT 4
|
||||
|
||||
#define STRIPROOT( path ) \
|
||||
( g_path_is_absolute( (path) ) ? g_path_skip_root( (path) ) : (path) )
|
||||
|
||||
struct addcb
|
||||
{
|
||||
GtkWidget * widget;
|
||||
TrCore * core;
|
||||
gboolean autostart;
|
||||
gboolean usingaltdir;
|
||||
GtkFileChooser *altdir;
|
||||
GtkButtonBox *altbox;
|
||||
};
|
||||
|
||||
struct dirdata
|
||||
{
|
||||
GtkWidget * widget;
|
||||
TrCore * core;
|
||||
GList * files;
|
||||
uint8_t * data;
|
||||
size_t size;
|
||||
enum tr_torrent_action action;
|
||||
gboolean paused;
|
||||
GtkWidget * widget;
|
||||
TrCore * core;
|
||||
GList * files;
|
||||
tr_ctor * ctor;
|
||||
};
|
||||
|
||||
static void
|
||||
addwindnocore( gpointer gdata, GObject * core );
|
||||
static void
|
||||
autoclick(GtkWidget *widget, gpointer gdata);
|
||||
static void
|
||||
dirclick(GtkWidget *widget, gpointer gdata);
|
||||
static void
|
||||
addresp(GtkWidget *widget, gint resp, gpointer gdata);
|
||||
static void
|
||||
promptdirnocore( gpointer gdata, GObject * core );
|
||||
static void
|
||||
promptresp( GtkWidget * widget, gint resp, gpointer data );
|
||||
|
||||
void
|
||||
makeaddwind( GtkWindow * parent, TrCore * core )
|
||||
promptdirnocore( gpointer gdata, GObject * core UNUSED )
|
||||
{
|
||||
GtkWidget *wind = gtk_file_chooser_dialog_new(_("Open Torrent"), parent,
|
||||
GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
|
||||
struct addcb *data = g_new(struct addcb, 1);
|
||||
GtkWidget *vbox = gtk_vbox_new(FALSE, 3);
|
||||
GtkWidget *bbox = gtk_hbutton_box_new();
|
||||
GtkWidget *autocheck = gtk_check_button_new_with_mnemonic(
|
||||
_("Automatically _start torrent"));
|
||||
GtkWidget *dircheck = gtk_check_button_new_with_mnemonic(
|
||||
_("Use alternate _download directory"));
|
||||
GtkFileFilter *filter = gtk_file_filter_new();
|
||||
GtkFileFilter *unfilter = gtk_file_filter_new();
|
||||
GtkWidget *getdir = gtk_file_chooser_button_new(
|
||||
_("Choose a download directory"), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
|
||||
char * pref;
|
||||
|
||||
data->widget = wind;
|
||||
data->core = core;
|
||||
data->autostart = TRUE;
|
||||
data->usingaltdir = FALSE;
|
||||
data->altdir = GTK_FILE_CHOOSER(getdir);
|
||||
data->altbox = GTK_BUTTON_BOX(bbox);
|
||||
|
||||
g_object_weak_ref( G_OBJECT( core ), addwindnocore, data );
|
||||
|
||||
gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_EDGE);
|
||||
gtk_box_pack_start_defaults(GTK_BOX(bbox), dircheck);
|
||||
gtk_box_pack_start_defaults(GTK_BOX(bbox), getdir);
|
||||
|
||||
gtk_box_pack_start_defaults(GTK_BOX(vbox), autocheck);
|
||||
gtk_box_pack_start_defaults(GTK_BOX(vbox), bbox);
|
||||
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(autocheck), TRUE);
|
||||
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);
|
||||
gtk_widget_set_sensitive(getdir, FALSE);
|
||||
|
||||
gtk_file_filter_set_name(filter, _("Torrent files"));
|
||||
gtk_file_filter_add_pattern(filter, "*.torrent");
|
||||
gtk_file_filter_set_name(unfilter, _("All files"));
|
||||
gtk_file_filter_add_pattern(unfilter, "*");
|
||||
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(wind), filter);
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(wind), unfilter);
|
||||
gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(wind), TRUE);
|
||||
gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(wind), vbox);
|
||||
|
||||
g_signal_connect(G_OBJECT(autocheck), "clicked", G_CALLBACK(autoclick),data);
|
||||
g_signal_connect(G_OBJECT(dircheck), "clicked", G_CALLBACK(dirclick), data);
|
||||
g_signal_connect(G_OBJECT(wind), "response", G_CALLBACK(addresp), data);
|
||||
|
||||
gtk_widget_show_all(wind);
|
||||
}
|
||||
|
||||
void
|
||||
addwindnocore( gpointer gdata, GObject * core UNUSED )
|
||||
{
|
||||
struct addcb * data = gdata;
|
||||
struct dirdata * stuff = gdata;
|
||||
|
||||
/* prevent the response callback from trying to remove the weak
|
||||
reference which no longer exists */
|
||||
data->core = NULL;
|
||||
stuff->core = NULL;
|
||||
|
||||
gtk_dialog_response( GTK_DIALOG( data->widget ), GTK_RESPONSE_NONE );
|
||||
gtk_dialog_response( GTK_DIALOG( stuff->widget ), GTK_RESPONSE_NONE );
|
||||
}
|
||||
|
||||
static void
|
||||
autoclick(GtkWidget *widget, gpointer gdata) {
|
||||
struct addcb *data = gdata;
|
||||
promptresp( GtkWidget * widget, gint resp, gpointer data )
|
||||
{
|
||||
struct dirdata * stuff;
|
||||
|
||||
data->autostart = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
|
||||
}
|
||||
stuff = data;
|
||||
|
||||
static void
|
||||
dirclick(GtkWidget *widget, gpointer gdata) {
|
||||
struct addcb *data = gdata;
|
||||
|
||||
data->usingaltdir = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
|
||||
gtk_widget_set_sensitive(GTK_WIDGET(data->altdir), data->usingaltdir);
|
||||
}
|
||||
|
||||
static void
|
||||
addresp(GtkWidget *widget, gint resp, gpointer gdata) {
|
||||
struct addcb *data = gdata;
|
||||
GSList *files, *ii;
|
||||
GList *stupidgtk;
|
||||
char *dir;
|
||||
enum tr_torrent_action action;
|
||||
|
||||
if(GTK_RESPONSE_ACCEPT == resp) {
|
||||
dir = NULL;
|
||||
if(data->usingaltdir)
|
||||
dir = gtk_file_chooser_get_filename(data->altdir);
|
||||
files = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(widget));
|
||||
action = tr_prefs_get_action( PREF_KEY_ADDSTD );
|
||||
|
||||
if( NULL == dir )
|
||||
if( GTK_RESPONSE_ACCEPT == resp )
|
||||
{
|
||||
stupidgtk = NULL;
|
||||
for( ii = files; NULL != ii; ii = ii->next )
|
||||
{
|
||||
stupidgtk = g_list_append( stupidgtk, ii->data );
|
||||
}
|
||||
tr_core_add_list( data->core, stupidgtk, action, !data->autostart );
|
||||
freestrlist(stupidgtk);
|
||||
}
|
||||
else
|
||||
{
|
||||
for( ii = files; NULL != ii; ii = ii->next )
|
||||
{
|
||||
tr_core_add_dir( data->core, ii->data, dir,
|
||||
action, !data->autostart );
|
||||
g_free( ii->data );
|
||||
}
|
||||
char * dir;
|
||||
GList * l;
|
||||
|
||||
/* update the destination */
|
||||
dir = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER( widget ) );
|
||||
tr_ctorSetDestination( stuff->ctor, TR_FORCE, dir );
|
||||
g_free( dir );
|
||||
|
||||
/* if there's metainfo in the ctor already, use it */
|
||||
if( !tr_ctorGetMetainfo( stuff->ctor, NULL ) )
|
||||
tr_core_add_ctor( stuff->core, stuff->ctor );
|
||||
|
||||
/* if there's a list of files, use them too */
|
||||
for( l=stuff->files; l!=NULL; l=l->next )
|
||||
if( !tr_ctorSetMetainfoFromFile( stuff->ctor, l->data ) )
|
||||
tr_core_add_ctor( stuff->core, stuff->ctor );
|
||||
}
|
||||
tr_core_torrents_added( data->core );
|
||||
g_slist_free(files);
|
||||
}
|
||||
|
||||
if( NULL != data->core )
|
||||
{
|
||||
g_object_weak_unref( G_OBJECT( data->core ), addwindnocore, data );
|
||||
}
|
||||
if( stuff->core )
|
||||
g_object_weak_unref( G_OBJECT( stuff->core ), promptdirnocore, stuff );
|
||||
|
||||
g_free( data );
|
||||
gtk_widget_destroy(widget);
|
||||
gtk_widget_destroy( widget );
|
||||
freestrlist( stuff->files );
|
||||
tr_ctorFree( stuff->ctor );
|
||||
g_free( stuff );
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -234,28 +105,32 @@ fmtpeercount( GtkLabel * label, int count )
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
promptfordir( GtkWindow * parent, TrCore * core, GList * files, uint8_t * data,
|
||||
size_t size, enum tr_torrent_action act, gboolean paused )
|
||||
static void
|
||||
deleteToggled( GtkToggleButton * tb, gpointer ctor )
|
||||
{
|
||||
char * path;
|
||||
tr_ctorSetDeleteSource( ctor, gtk_toggle_button_get_active( tb ) );
|
||||
}
|
||||
|
||||
static void
|
||||
startToggled( GtkToggleButton * tb, gpointer ctor )
|
||||
{
|
||||
tr_ctorSetPaused( ctor, TR_FORCE, !gtk_toggle_button_get_active( tb ) );
|
||||
}
|
||||
|
||||
void
|
||||
promptfordir( GtkWindow * parent, TrCore * core, GList * files, tr_ctor * ctor )
|
||||
{
|
||||
uint8_t flag = 0;
|
||||
const char * str;
|
||||
struct dirdata * stuff;
|
||||
GtkWidget * wind;
|
||||
GtkWidget * v;
|
||||
GtkWidget * w;
|
||||
|
||||
stuff = g_new0( struct dirdata, 1 );
|
||||
stuff->core = core;
|
||||
if( NULL != files )
|
||||
{
|
||||
stuff->files = dupstrlist( files );
|
||||
}
|
||||
if( NULL != data )
|
||||
{
|
||||
stuff->data = g_new( uint8_t, size );
|
||||
memcpy( stuff->data, data, size );
|
||||
stuff->size = size;
|
||||
}
|
||||
stuff->action = act;
|
||||
stuff->paused = paused;
|
||||
stuff->core = core;
|
||||
stuff->ctor = ctor;
|
||||
stuff->files = dupstrlist( files );
|
||||
|
||||
g_object_weak_ref( G_OBJECT( core ), promptdirnocore, stuff );
|
||||
|
||||
|
@ -266,9 +141,24 @@ 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 );
|
||||
path = getdownloaddir( );
|
||||
gtk_file_chooser_set_filename( GTK_FILE_CHOOSER( wind ), path );
|
||||
g_free( path );
|
||||
tr_ctorGetDestination( ctor, TR_FORCE, &str );
|
||||
gtk_file_chooser_set_uri( GTK_FILE_CHOOSER( wind ), str );
|
||||
|
||||
v = gtk_vbox_new( FALSE, GUI_PAD );
|
||||
|
||||
w = gtk_check_button_new_with_mnemonic( _( "_Delete original torrent file" ) );
|
||||
g_signal_connect( w, "toggled", G_CALLBACK( deleteToggled ), ctor );
|
||||
tr_ctorGetDeleteSource( ctor, &flag );
|
||||
gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( w ), flag );
|
||||
gtk_box_pack_start( GTK_BOX( v ), w, FALSE, FALSE, 0 );
|
||||
|
||||
w = gtk_check_button_new_with_mnemonic( _( "_Start when added" ) );
|
||||
g_signal_connect( w, "toggled", G_CALLBACK( startToggled ), ctor );
|
||||
tr_ctorGetPaused( ctor, TR_FORCE, &flag );
|
||||
gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( w ), !flag );
|
||||
gtk_box_pack_start( GTK_BOX( v ), w, FALSE, FALSE, 0 );
|
||||
|
||||
gtk_file_chooser_set_extra_widget( GTK_FILE_CHOOSER( wind ), v );
|
||||
|
||||
stuff->widget = wind;
|
||||
|
||||
|
@ -278,57 +168,6 @@ promptfordir( GtkWindow * parent, TrCore * core, GList * files, uint8_t * data,
|
|||
gtk_widget_show_all(wind);
|
||||
}
|
||||
|
||||
void
|
||||
promptdirnocore( gpointer gdata, GObject * core UNUSED )
|
||||
{
|
||||
struct dirdata * stuff = gdata;
|
||||
|
||||
/* prevent the response callback from trying to remove the weak
|
||||
reference which no longer exists */
|
||||
stuff->core = NULL;
|
||||
|
||||
gtk_dialog_response( GTK_DIALOG( stuff->widget ), GTK_RESPONSE_NONE );
|
||||
}
|
||||
|
||||
static void
|
||||
promptresp( GtkWidget * widget, gint resp, gpointer data )
|
||||
{
|
||||
struct dirdata * stuff;
|
||||
char * dir;
|
||||
GList * ii;
|
||||
|
||||
stuff = data;
|
||||
|
||||
if( GTK_RESPONSE_ACCEPT == resp )
|
||||
{
|
||||
dir = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER( widget ) );
|
||||
/* it seems that we will always get a directory */
|
||||
g_assert( NULL != dir );
|
||||
for( ii = g_list_first( stuff->files ); NULL != ii; ii = ii->next )
|
||||
{
|
||||
tr_core_add_dir( stuff->core, ii->data, dir,
|
||||
stuff->action, stuff->paused );
|
||||
}
|
||||
if( NULL != stuff->data )
|
||||
{
|
||||
tr_core_add_data_dir( stuff->core, stuff->data, stuff->size, dir,
|
||||
stuff->paused );
|
||||
}
|
||||
tr_core_torrents_added( stuff->core );
|
||||
g_free( dir );
|
||||
}
|
||||
|
||||
if( NULL != stuff->core )
|
||||
{
|
||||
g_object_weak_unref( G_OBJECT( stuff->core ), promptdirnocore, stuff );
|
||||
}
|
||||
|
||||
freestrlist( stuff->files );
|
||||
g_free( stuff->data );
|
||||
g_free( stuff );
|
||||
gtk_widget_destroy( widget );
|
||||
}
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
@ -345,9 +184,11 @@ static void
|
|||
quitresp( GtkWidget * widget, int response, gpointer data )
|
||||
{
|
||||
struct quitdata * stuff = data;
|
||||
GtkToggleButton * tb = GTK_TOGGLE_BUTTON( stuff->dontask );
|
||||
|
||||
pref_flag_set( PREF_KEY_ASKQUIT,
|
||||
!gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(stuff->dontask) ) );
|
||||
tr_core_set_pref_bool( stuff->core,
|
||||
PREF_KEY_ASKQUIT,
|
||||
!gtk_toggle_button_get_active( tb ) );
|
||||
|
||||
if( response == GTK_RESPONSE_ACCEPT )
|
||||
stuff->func( stuff->cbdata );
|
||||
|
|
|
@ -29,17 +29,10 @@
|
|||
#include "tr_torrent.h"
|
||||
#include "util.h"
|
||||
|
||||
/* show the "add a torrent" dialog */
|
||||
void
|
||||
makeaddwind( GtkWindow * parent, TrCore * core );
|
||||
|
||||
/* prompt for a download directory for torrents, then add them */
|
||||
void
|
||||
promptfordir( GtkWindow * parent, TrCore * core, GList * files, uint8_t * data,
|
||||
size_t size, enum tr_torrent_action act, gboolean paused );
|
||||
void promptfordir( GtkWindow* parent, TrCore*, GList* filenames, tr_ctor* );
|
||||
|
||||
/* prompt if the user wants to quit, calls func with cbdata if they do */
|
||||
void
|
||||
askquit( TrCore*, GtkWindow* parent, callbackfunc_t func, void * cbdata );
|
||||
void askquit( TrCore*, GtkWindow* parent, callbackfunc_t func, void* cbdata );
|
||||
|
||||
#endif /* TG_PREFS_H */
|
||||
|
|
|
@ -374,6 +374,9 @@ static void
|
|||
torrentDestroyed( gpointer gdata, GObject * deadTorrent UNUSED )
|
||||
{
|
||||
FileData * data = gdata;
|
||||
|
||||
g_object_weak_unref( G_OBJECT( data->gtor ), torrentDestroyed, data );
|
||||
|
||||
file_list_set_torrent( data->top, NULL );
|
||||
}
|
||||
|
||||
|
|
58
gtk/ipc.c
58
gtk/ipc.c
|
@ -579,9 +579,10 @@ smsg_add( enum ipc_msg id UNUSED, benc_val_t * val, int64_t tag, void * arg )
|
|||
{
|
||||
struct constate * con = arg;
|
||||
struct constate_serv * srv = &con->u.serv;
|
||||
enum tr_torrent_action action;
|
||||
benc_val_t * path;
|
||||
int ii;
|
||||
tr_ctor * ctor;
|
||||
GList * list = NULL;
|
||||
|
||||
if( NULL == val || TYPE_LIST != val->type )
|
||||
{
|
||||
|
@ -589,7 +590,8 @@ smsg_add( enum ipc_msg id UNUSED, benc_val_t * val, int64_t tag, void * arg )
|
|||
return;
|
||||
}
|
||||
|
||||
action = tr_prefs_get_action( PREF_KEY_ADDIPC );
|
||||
ctor = tr_ctorNew( srv->core );
|
||||
|
||||
for( ii = 0; ii < val->val.l.count; ii++ )
|
||||
{
|
||||
path = val->val.l.vals + ii;
|
||||
|
@ -597,10 +599,14 @@ smsg_add( enum ipc_msg id UNUSED, benc_val_t * val, int64_t tag, void * arg )
|
|||
/* XXX somehow escape invalid utf-8 */
|
||||
g_utf8_validate( path->val.s.s, path->val.s.i, NULL ) )
|
||||
{
|
||||
tr_core_add( TR_CORE( srv->core ), path->val.s.s, action, FALSE );
|
||||
list = g_list_append( list, g_strndup( path->val.s.s, path->val.s.i ) );
|
||||
}
|
||||
}
|
||||
tr_core_torrents_added( TR_CORE( srv->core ) );
|
||||
|
||||
if( list ) {
|
||||
tr_core_add_list( srv->core, list, ctor );
|
||||
tr_core_torrents_added( TR_CORE( srv->core ) );
|
||||
}
|
||||
|
||||
/* XXX should send info response back with torrent ids */
|
||||
simpleresp( con, tag, IPC_MSG_OK );
|
||||
|
@ -612,9 +618,8 @@ smsg_addone( enum ipc_msg id UNUSED, benc_val_t * val, int64_t tag,
|
|||
{
|
||||
struct constate * con = arg;
|
||||
struct constate_serv * srv = &con->u.serv;
|
||||
enum tr_torrent_action action;
|
||||
benc_val_t * file, * data, * dir, * start;
|
||||
gboolean paused;
|
||||
tr_ctor * ctor;
|
||||
|
||||
if( NULL == val || TYPE_DICT != val->type )
|
||||
{
|
||||
|
@ -636,33 +641,18 @@ smsg_addone( enum ipc_msg id UNUSED, benc_val_t * val, int64_t tag,
|
|||
return;
|
||||
}
|
||||
|
||||
action = tr_prefs_get_action( PREF_KEY_ADDIPC );
|
||||
paused = ( NULL == start || start->val.i ? FALSE : TRUE );
|
||||
if( NULL != file )
|
||||
{
|
||||
if( NULL == dir )
|
||||
{
|
||||
tr_core_add( srv->core, file->val.s.s, action, paused );
|
||||
}
|
||||
else
|
||||
{
|
||||
tr_core_add_dir( srv->core, file->val.s.s, dir->val.s.s,
|
||||
action, paused );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( NULL == dir )
|
||||
{
|
||||
tr_core_add_data( srv->core, (uint8_t *) data->val.s.s,
|
||||
data->val.s.i, paused );
|
||||
}
|
||||
else
|
||||
{
|
||||
tr_core_add_data_dir( srv->core, (uint8_t *) data->val.s.s,
|
||||
data->val.s.i, dir->val.s.s, paused );
|
||||
}
|
||||
}
|
||||
ctor = tr_ctorNew( tr_core_handle( srv->core ) );
|
||||
if( dir )
|
||||
tr_ctorSetDestination( ctor, TR_FORCE, dir->val.s.s );
|
||||
if( file )
|
||||
tr_ctorSetMetainfoFromFile( ctor, file->val.s.s );
|
||||
if( data )
|
||||
tr_ctorSetMetainfo( ctor, (uint8_t*)data->val.s.s, data->val.s.i );
|
||||
if( start )
|
||||
tr_ctorSetPaused( ctor, TR_FORCE, !start->val.i );
|
||||
|
||||
tr_core_add_ctor( TR_CORE( srv->core ), ctor );
|
||||
|
||||
tr_core_torrents_added( TR_CORE( srv->core ) );
|
||||
|
||||
/* XXX should send info response back with torrent ids */
|
||||
|
@ -998,7 +988,7 @@ smsg_pref( enum ipc_msg id, benc_val_t * val UNUSED, int64_t tag, void * arg )
|
|||
break;
|
||||
case IPC_MSG_GETDIR:
|
||||
/* XXX sending back "" when we're prompting is kind of bogus */
|
||||
pref = pref_flag_get( PREF_KEY_DIR_ASK ) ? "" : getdownloaddir();
|
||||
pref = pref_flag_get( PREF_KEY_OPTIONS_PROMPT ) ? "" : getdownloaddir();
|
||||
buf = ipc_mkstr( con->ipc, &size, IPC_MSG_DIR, tag, pref );
|
||||
break;
|
||||
case IPC_MSG_GETDOWNLIMIT:
|
||||
|
|
52
gtk/main.c
52
gtk/main.c
|
@ -47,6 +47,7 @@
|
|||
#include "ipc.h"
|
||||
#include "makemeta-ui.h"
|
||||
#include "msgwin.h"
|
||||
#include "open.h"
|
||||
#include "stats.h"
|
||||
#include "torrent-inspector.h"
|
||||
#include "tr_core.h"
|
||||
|
@ -146,9 +147,7 @@ static void
|
|||
coreerr( TrCore * core, enum tr_core_err code, const char * msg,
|
||||
gpointer gdata );
|
||||
static void
|
||||
coreprompt( TrCore *, GList *, enum tr_torrent_action, gboolean, gpointer );
|
||||
static void
|
||||
corepromptdata( TrCore *, uint8_t *, size_t, gboolean, gpointer );
|
||||
coreprompt( TrCore *, GList *, gpointer, gpointer );
|
||||
static void
|
||||
initializeFromPrefs( struct cbdata * cbdata );
|
||||
static void
|
||||
|
@ -329,10 +328,8 @@ sendremote( GList * files, gboolean sendquit )
|
|||
static void
|
||||
appsetup( TrWindow * wind, GList * args,
|
||||
struct cbdata * cbdata,
|
||||
gboolean paused, gboolean minimized )
|
||||
gboolean forcepause, gboolean minimized )
|
||||
{
|
||||
enum tr_torrent_action action;
|
||||
|
||||
/* fill out cbdata */
|
||||
cbdata->wind = NULL;
|
||||
cbdata->icon = NULL;
|
||||
|
@ -349,8 +346,6 @@ appsetup( TrWindow * wind, GList * args,
|
|||
g_signal_connect( cbdata->core, "error", G_CALLBACK( coreerr ), cbdata );
|
||||
g_signal_connect( cbdata->core, "directory-prompt",
|
||||
G_CALLBACK( coreprompt ), cbdata );
|
||||
g_signal_connect( cbdata->core, "directory-prompt-data",
|
||||
G_CALLBACK( corepromptdata ), cbdata );
|
||||
g_signal_connect_swapped( cbdata->core, "quit",
|
||||
G_CALLBACK( wannaquit ), cbdata );
|
||||
g_signal_connect( cbdata->core, "prefs-changed",
|
||||
|
@ -363,12 +358,14 @@ appsetup( TrWindow * wind, GList * args,
|
|||
initializeFromPrefs( cbdata );
|
||||
|
||||
/* add torrents from command-line and saved state */
|
||||
tr_core_load( cbdata->core, paused );
|
||||
tr_core_load( cbdata->core, forcepause );
|
||||
|
||||
if( NULL != args )
|
||||
{
|
||||
action = tr_prefs_get_action( PREF_KEY_ADDIPC );
|
||||
tr_core_add_list( cbdata->core, args, action, paused );
|
||||
tr_ctor * ctor = tr_ctorNew( tr_core_handle( cbdata->core ) );
|
||||
if( forcepause )
|
||||
tr_ctorSetPaused( ctor, TR_FORCE, TRUE );
|
||||
tr_core_add_list( cbdata->core, args, ctor );
|
||||
}
|
||||
tr_core_torrents_added( cbdata->core );
|
||||
|
||||
|
@ -625,7 +622,8 @@ gotdrag( GtkWidget * widget UNUSED,
|
|||
GList * paths = NULL;
|
||||
GList * freeme = NULL;
|
||||
|
||||
#ifdef DND_DEBUG
|
||||
#if 0
|
||||
int i;
|
||||
char *sele = gdk_atom_name(sel->selection);
|
||||
char *targ = gdk_atom_name(sel->target);
|
||||
char *type = gdk_atom_name(sel->type);
|
||||
|
@ -683,9 +681,9 @@ gotdrag( GtkWidget * widget UNUSED,
|
|||
/* try to add any torrents we found */
|
||||
if( paths != NULL )
|
||||
{
|
||||
enum tr_torrent_action action = tr_prefs_get_action( PREF_KEY_ADDSTD );
|
||||
tr_ctor * ctor = tr_ctorNew( tr_core_handle( data->core ) );
|
||||
paths = g_list_reverse( paths );
|
||||
tr_core_add_list( data->core, paths, action, FALSE );
|
||||
tr_core_add_list( data->core, paths, ctor );
|
||||
tr_core_torrents_added( data->core );
|
||||
g_list_free( paths );
|
||||
}
|
||||
|
@ -748,22 +746,20 @@ coreerr( TrCore * core UNUSED, enum tr_core_err code, const char * msg,
|
|||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
void
|
||||
coreprompt( TrCore * core, GList * paths, enum tr_torrent_action act,
|
||||
gboolean paused, gpointer gdata )
|
||||
static void
|
||||
coreprompt( TrCore * core,
|
||||
GList * paths,
|
||||
gpointer ctor,
|
||||
gpointer gdata )
|
||||
{
|
||||
struct cbdata * cbdata = gdata;
|
||||
|
||||
promptfordir( cbdata->wind, core, paths, NULL, 0, act, paused );
|
||||
}
|
||||
|
||||
void
|
||||
corepromptdata( TrCore * core, uint8_t * data, size_t size,
|
||||
gboolean paused, gpointer gdata )
|
||||
{
|
||||
struct cbdata * cbdata = gdata;
|
||||
|
||||
promptfordir( cbdata->wind, core, NULL, data, size, TR_TOR_LEAVE, paused );
|
||||
if( g_list_length( paths ) != 1 )
|
||||
promptfordir( cbdata->wind, core, paths, ctor );
|
||||
else {
|
||||
tr_ctorSetMetainfoFromFile( ctor, paths->data );
|
||||
makeaddwind( cbdata->wind, core, ctor );
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1013,7 +1009,7 @@ doAction ( const char * action_name, gpointer user_data )
|
|||
|
||||
if ( !strcmp (action_name, "open-torrent-menu") || !strcmp( action_name, "open-torrent-toolbar" ))
|
||||
{
|
||||
makeaddwind( data->wind, data->core );
|
||||
makeaddwind( data->wind, data->core, tr_ctorNew( tr_core_handle( data->core ) ) );
|
||||
}
|
||||
else if (!strcmp (action_name, "show-stats"))
|
||||
{
|
||||
|
|
|
@ -2,4 +2,4 @@
|
|||
export G_SLICE=always-malloc
|
||||
export G_DEBUG=gc-friendly
|
||||
export GLIBCXX_FORCE_NEW=1
|
||||
valgrind --tool=memcheck --leak-check=full --leak-resolution=high --num-callers=64 --log-file=x-valgrind --show-reachable=yes ./transmission
|
||||
valgrind --tool=memcheck --leak-check=full --leak-resolution=high --num-callers=64 --log-file=x-valgrind --show-reachable=yes ./transmission ~/Desktop/*torrent
|
||||
|
|
|
@ -0,0 +1,223 @@
|
|||
/*
|
||||
* This file Copyright (C) 2008 Charles Kerr <charles@rebelbase.com>
|
||||
*
|
||||
* 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: hig.h 4404 2008-01-01 17:20:20Z charles $
|
||||
*/
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include "file-list.h"
|
||||
#include "hig.h"
|
||||
#include "open.h"
|
||||
|
||||
struct OpenData
|
||||
{
|
||||
TrCore * core;
|
||||
GtkWidget * list;
|
||||
GtkWidget * run_check;
|
||||
char * filename;
|
||||
char * destination;
|
||||
TrTorrent * gtor;
|
||||
tr_ctor * ctor;
|
||||
};
|
||||
|
||||
static void
|
||||
deleteOldTorrent( struct OpenData * data )
|
||||
{
|
||||
if( data->gtor )
|
||||
{
|
||||
tr_torrent * tor = tr_torrent_handle( data->gtor );
|
||||
tr_torrentRemoveSaved( tor );
|
||||
tr_torrentClose( tor );
|
||||
g_object_unref( G_OBJECT( data->gtor ) );
|
||||
data->gtor = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
openResponseCB( GtkDialog * dialog, gint response, gpointer gdata )
|
||||
{
|
||||
struct OpenData * data = gdata;
|
||||
|
||||
if( data->gtor )
|
||||
{
|
||||
if( response != GTK_RESPONSE_ACCEPT )
|
||||
deleteOldTorrent( data );
|
||||
else {
|
||||
if( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( data->run_check ) ) )
|
||||
tr_torrentStart( tr_torrent_handle( data->gtor ) );
|
||||
tr_core_add_torrent( data->core, data->gtor );
|
||||
}
|
||||
}
|
||||
|
||||
tr_ctorFree( data->ctor );
|
||||
g_free( data->filename );
|
||||
g_free( data->destination );
|
||||
g_free( data );
|
||||
gtk_widget_destroy( GTK_WIDGET( dialog ) );
|
||||
}
|
||||
|
||||
static void
|
||||
updateTorrent( struct OpenData * data )
|
||||
{
|
||||
if( data->gtor )
|
||||
tr_torrentSetFolder( tr_torrent_handle( data->gtor ), data->destination );
|
||||
|
||||
file_list_set_torrent( data->list, data->gtor );
|
||||
}
|
||||
|
||||
static void
|
||||
sourceChanged( GtkFileChooserButton * b, gpointer gdata )
|
||||
{
|
||||
struct OpenData * data = gdata;
|
||||
|
||||
deleteOldTorrent( data );
|
||||
|
||||
/* update the filename */
|
||||
g_free( data->filename );
|
||||
data->filename = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER( b ) );
|
||||
|
||||
/* maybe instantiate a torrent */
|
||||
if( data->filename ) {
|
||||
int err = 0;
|
||||
tr_torrent * torrent;
|
||||
tr_handle * handle = tr_core_handle( data->core );
|
||||
tr_ctorSetMetainfoFromFile( data->ctor, data->filename );
|
||||
tr_ctorSetPaused( data->ctor, TR_FORCE, TRUE );
|
||||
tr_ctorSetDestination( data->ctor, TR_FORCE, data->destination );
|
||||
if(( torrent = tr_torrentNew( handle, data->ctor, &err )))
|
||||
data->gtor = tr_torrent_new_preexisting( torrent );
|
||||
}
|
||||
|
||||
updateTorrent( data );
|
||||
}
|
||||
|
||||
static void
|
||||
verifyRequested( GtkButton * button UNUSED, gpointer gdata )
|
||||
{
|
||||
struct OpenData * data = gdata;
|
||||
if( data->gtor )
|
||||
tr_torrentRecheck( tr_torrent_handle( data->gtor ) );
|
||||
}
|
||||
|
||||
static void
|
||||
destinationChanged( GtkFileChooserButton * b, gpointer gdata )
|
||||
{
|
||||
struct OpenData * data = gdata;
|
||||
g_free( data->destination );
|
||||
data->destination = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER( b ) );
|
||||
|
||||
updateTorrent( data );
|
||||
verifyRequested( NULL, data );
|
||||
}
|
||||
|
||||
/****
|
||||
*****
|
||||
****/
|
||||
|
||||
void
|
||||
makeaddwind( GtkWindow * parent,
|
||||
TrCore * core,
|
||||
tr_ctor * ctor )
|
||||
{
|
||||
int row;
|
||||
int col;
|
||||
const char * str;
|
||||
GtkWidget * w;
|
||||
GtkWidget * d;
|
||||
GtkWidget * t;
|
||||
GtkWidget * l;
|
||||
GtkFileFilter * filter;
|
||||
struct OpenData * data;
|
||||
uint8_t flag;
|
||||
|
||||
/* make the dialog */
|
||||
d = gtk_dialog_new_with_buttons( _( "Open Torrent" ),
|
||||
parent,
|
||||
GTK_DIALOG_DESTROY_WITH_PARENT|GTK_DIALOG_NO_SEPARATOR,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
|
||||
NULL );
|
||||
|
||||
tr_ctorGetDestination( ctor, TR_FORCE, &str );
|
||||
data = g_new0( struct OpenData, 1 );
|
||||
data->core = core;
|
||||
data->ctor = ctor;
|
||||
data->filename = g_strdup( tr_ctorGetSourceFile( ctor ) );
|
||||
data->destination = g_strdup( str );
|
||||
g_signal_connect( G_OBJECT( d ), "response", G_CALLBACK( openResponseCB ), data );
|
||||
|
||||
t = gtk_table_new( 6, 2, FALSE );
|
||||
gtk_container_set_border_width( GTK_CONTAINER( t ), GUI_PAD_BIG );
|
||||
gtk_table_set_row_spacings( GTK_TABLE( t ), GUI_PAD );
|
||||
gtk_table_set_col_spacings( GTK_TABLE( t ), GUI_PAD_BIG );
|
||||
|
||||
row = col = 0;
|
||||
l = gtk_label_new_with_mnemonic( _( "_Torrent file:" ) );
|
||||
gtk_misc_set_alignment( GTK_MISC( l ), 0.0f, 0.5f );
|
||||
gtk_table_attach( GTK_TABLE( t ), l, col, col+1, row, row+1, GTK_FILL, 0, 0, 0 );
|
||||
++col;
|
||||
w = gtk_file_chooser_button_new( _( "Select Torrent" ), GTK_FILE_CHOOSER_ACTION_OPEN );
|
||||
gtk_table_attach( GTK_TABLE( t ), w, col, col+1, row, row+1, ~0, 0, 0, 0 );
|
||||
gtk_label_set_mnemonic_widget( GTK_LABEL( l ), w );
|
||||
filter = gtk_file_filter_new( );
|
||||
gtk_file_filter_set_name( filter, _( "Torrent files" ) );
|
||||
gtk_file_filter_add_pattern( filter, "*.torrent" );
|
||||
gtk_file_chooser_add_filter( GTK_FILE_CHOOSER( w ), filter );
|
||||
filter = gtk_file_filter_new( );
|
||||
gtk_file_filter_set_name( filter, _( "All files" ) );
|
||||
gtk_file_filter_add_pattern( filter, "*" );
|
||||
gtk_file_chooser_add_filter( GTK_FILE_CHOOSER( w ), filter );
|
||||
g_signal_connect( w, "selection-changed", G_CALLBACK( sourceChanged ), data );
|
||||
if( data->filename )
|
||||
gtk_file_chooser_set_uri( GTK_FILE_CHOOSER( w ), data->filename );
|
||||
|
||||
++row;
|
||||
col = 0;
|
||||
l = gtk_label_new_with_mnemonic( _( "Download _to:" ) );
|
||||
gtk_misc_set_alignment( GTK_MISC( l ), 0.0f, 0.5f );
|
||||
gtk_table_attach( GTK_TABLE( t ), l, col, col+1, row, row+1, GTK_FILL, 0, 0, 0 );
|
||||
++col;
|
||||
w = gtk_file_chooser_button_new( _( "Destination" ), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER );
|
||||
gtk_file_chooser_set_uri( GTK_FILE_CHOOSER( w ), data->destination );
|
||||
gtk_table_attach( GTK_TABLE( t ), w, col, col+1, row, row+1, ~0, 0, 0, 0 );
|
||||
gtk_label_set_mnemonic_widget( GTK_LABEL( l ), w );
|
||||
g_signal_connect( w, "selection-changed", G_CALLBACK( destinationChanged ), data );
|
||||
|
||||
++row;
|
||||
col = 0;
|
||||
w = file_list_new( NULL );
|
||||
gtk_widget_set_size_request ( w, 466u, 300u );
|
||||
data->list = w;
|
||||
gtk_table_attach_defaults( GTK_TABLE( t ), w, col, col+2, row, row+1 );
|
||||
|
||||
++row;
|
||||
col = 0;
|
||||
w = gtk_button_new_with_mnemonic( _( "Verify Local Data" ) );
|
||||
gtk_table_attach( GTK_TABLE( t ), w, col, col+1, row, row+1, GTK_FILL, 0, 0, 0 );
|
||||
g_signal_connect( w, "clicked", G_CALLBACK( verifyRequested ), data );
|
||||
|
||||
++row;
|
||||
col = 0;
|
||||
w = gtk_check_button_new_with_mnemonic( _( "_Delete original torrent file" ) );
|
||||
tr_ctorGetDeleteSource( ctor, &flag );
|
||||
gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( w ), flag );
|
||||
gtk_table_attach( GTK_TABLE( t ), w, col, col+2, row, row+1, GTK_FILL, 0, 0, 0 );
|
||||
|
||||
++row;
|
||||
col = 0;
|
||||
w = gtk_check_button_new_with_mnemonic( _( "_Start when added" ) );
|
||||
data->run_check = w;
|
||||
tr_ctorGetPaused( ctor, TR_FORCE, &flag );
|
||||
gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( w ), !flag );
|
||||
gtk_table_attach( GTK_TABLE( t ), w, col, col+2, row, row+1, GTK_FILL, 0, 0, 0 );
|
||||
|
||||
gtk_box_pack_start_defaults( GTK_BOX( GTK_DIALOG( d )->vbox ), t );
|
||||
gtk_widget_show_all( d );
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* This file Copyright (C) 2008 Charles Kerr <charles@rebelbase.com>
|
||||
*
|
||||
* 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: hig.h 4404 2008-01-01 17:20:20Z charles $
|
||||
*/
|
||||
|
||||
#ifndef TR_GTK_OPEN_DIALOG_H
|
||||
#define TR_GTK_OPEN_DIALOG_H
|
||||
|
||||
#include <gtk/gtkwindow.h>
|
||||
#include "tr_core.h"
|
||||
|
||||
void makeaddwind( GtkWindow * parent,
|
||||
TrCore * core,
|
||||
tr_ctor * ctor );
|
||||
|
||||
#endif /* TR_GTK_OPEN_DIALOG */
|
211
gtk/tr_core.c
211
gtk/tr_core.c
|
@ -77,53 +77,23 @@ tr_core_marshal_prompt( GClosure * closure, GValue * ret UNUSED, guint count,
|
|||
const GValue * vals, gpointer hint UNUSED,
|
||||
gpointer marshal )
|
||||
{
|
||||
typedef void (*TRMarshalPrompt)
|
||||
( gpointer, GList *, enum tr_torrent_action, gboolean, gpointer );
|
||||
typedef void (*TRMarshalPrompt)( gpointer, GList *, gpointer, gpointer );
|
||||
TRMarshalPrompt callback;
|
||||
GCClosure * cclosure = (GCClosure*) closure;
|
||||
GList * paths;
|
||||
enum tr_torrent_action action;
|
||||
gboolean paused;
|
||||
gpointer ctor;
|
||||
gpointer inst, gdata;
|
||||
|
||||
g_return_if_fail( 4 == count );
|
||||
g_return_if_fail( 3 == count );
|
||||
|
||||
inst = g_value_peek_pointer( vals );
|
||||
paths = g_value_get_pointer( vals + 1 );
|
||||
action = g_value_get_int( vals + 2 );
|
||||
paused = g_value_get_boolean( vals + 3 );
|
||||
gdata = closure->data;
|
||||
inst = g_value_peek_pointer( vals );
|
||||
paths = g_value_get_pointer( vals + 1 );
|
||||
ctor = g_value_get_pointer( vals + 2 );
|
||||
gdata = closure->data;
|
||||
|
||||
callback = (TRMarshalPrompt) ( NULL == marshal ?
|
||||
cclosure->callback : marshal );
|
||||
callback( inst, paths, action, paused, gdata );
|
||||
}
|
||||
|
||||
static void
|
||||
tr_core_marshal_data( GClosure * closure, GValue * ret UNUSED, guint count,
|
||||
const GValue * vals, gpointer hint UNUSED,
|
||||
gpointer marshal )
|
||||
{
|
||||
typedef void (*TRMarshalPrompt)
|
||||
( gpointer, uint8_t *, size_t, gboolean, gpointer );
|
||||
TRMarshalPrompt callback;
|
||||
GCClosure * cclosure = (GCClosure*) closure;
|
||||
uint8_t * data;
|
||||
size_t size;
|
||||
gboolean paused;
|
||||
gpointer inst, gdata;
|
||||
|
||||
g_return_if_fail( 4 == count );
|
||||
|
||||
inst = g_value_peek_pointer( vals );
|
||||
data = (uint8_t *) g_value_get_string( vals + 1 );
|
||||
size = g_value_get_uint( vals + 2 );
|
||||
paused = g_value_get_boolean( vals + 3 );
|
||||
gdata = closure->data;
|
||||
|
||||
callback = (TRMarshalPrompt) ( NULL == marshal ?
|
||||
cclosure->callback : marshal );
|
||||
callback( inst, data, size, paused, gdata );
|
||||
callback( inst, paths, ctor, gdata );
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -171,14 +141,7 @@ tr_core_class_init( gpointer g_class, gpointer g_class_data UNUSED )
|
|||
G_TYPE_FROM_CLASS( g_class ),
|
||||
G_SIGNAL_RUN_LAST, 0, NULL, NULL,
|
||||
tr_core_marshal_prompt, G_TYPE_NONE,
|
||||
3, G_TYPE_POINTER, G_TYPE_INT,
|
||||
G_TYPE_BOOLEAN );
|
||||
core_class->promptdatasig = g_signal_new( "directory-prompt-data",
|
||||
G_TYPE_FROM_CLASS( g_class ),
|
||||
G_SIGNAL_RUN_LAST, 0, NULL, NULL,
|
||||
tr_core_marshal_data,
|
||||
G_TYPE_NONE, 3, G_TYPE_STRING,
|
||||
G_TYPE_UINT, G_TYPE_BOOLEAN );
|
||||
2, G_TYPE_POINTER, G_TYPE_POINTER );
|
||||
core_class->quitsig = g_signal_new( "quit", G_TYPE_FROM_CLASS( g_class ),
|
||||
G_SIGNAL_RUN_LAST, 0, NULL, NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
|
@ -486,14 +449,15 @@ doCollate( const char * in )
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
tr_core_insert( TrCore * self, TrTorrent * tor )
|
||||
void
|
||||
tr_core_add_torrent( TrCore * self, TrTorrent * tor )
|
||||
{
|
||||
const tr_info * inf = tr_torrent_info( tor );
|
||||
const tr_stat * torStat = tr_torrent_stat( tor );
|
||||
char * collated = doCollate( inf->name );
|
||||
GtkListStore * store = GTK_LIST_STORE( tr_core_model( self ) );
|
||||
GtkTreeIter unused;
|
||||
|
||||
gtk_list_store_insert_with_values( store, &unused, 0,
|
||||
MC_NAME, inf->name,
|
||||
MC_NAME_COLLATED, collated,
|
||||
|
@ -503,8 +467,10 @@ tr_core_insert( TrCore * self, TrTorrent * tor )
|
|||
MC_STATUS, torStat->status,
|
||||
MC_ID, self->priv->nextid,
|
||||
-1);
|
||||
self->priv->nextid++;
|
||||
g_object_unref( tor );
|
||||
++self->priv->nextid;
|
||||
|
||||
/* cleanup */
|
||||
g_object_unref( G_OBJECT( tor ) );
|
||||
g_free( collated );
|
||||
}
|
||||
|
||||
|
@ -529,7 +495,7 @@ tr_core_load( TrCore * self, gboolean forcePaused )
|
|||
|
||||
torrents = tr_loadTorrents ( tr_core_handle( self ), ctor, &count );
|
||||
for( i=0; i<count; ++i )
|
||||
tr_core_insert( self, tr_torrent_new_preexisting( torrents[i] ) );
|
||||
tr_core_add_torrent( self, tr_torrent_new_preexisting( torrents[i] ) );
|
||||
|
||||
tr_free( torrents );
|
||||
tr_ctorFree( ctor );
|
||||
|
@ -538,22 +504,6 @@ tr_core_load( TrCore * self, gboolean forcePaused )
|
|||
return count;
|
||||
}
|
||||
|
||||
gboolean
|
||||
tr_core_add( TrCore * self, const char * path, enum tr_torrent_action act,
|
||||
gboolean paused )
|
||||
{
|
||||
GList * list;
|
||||
int ret;
|
||||
|
||||
TR_IS_CORE( self );
|
||||
|
||||
list = g_list_append( NULL, (void *) path );
|
||||
ret = tr_core_add_list( self, list, act, paused );
|
||||
g_list_free( list );
|
||||
|
||||
return 1 == ret;
|
||||
}
|
||||
|
||||
static void
|
||||
tr_core_errsig( TrCore * self, enum tr_core_err type, const char * msg )
|
||||
{
|
||||
|
@ -563,105 +513,72 @@ tr_core_errsig( TrCore * self, enum tr_core_err type, const char * msg )
|
|||
g_signal_emit( self, class->errsig, 0, type, msg );
|
||||
}
|
||||
|
||||
gboolean
|
||||
tr_core_add_dir( TrCore * self, const char * path, const char * dir,
|
||||
enum tr_torrent_action act, gboolean paused )
|
||||
static void
|
||||
tr_core_apply_defaults( tr_ctor * ctor )
|
||||
{
|
||||
if( tr_ctorGetPaused( ctor, TR_FORCE, NULL ) )
|
||||
tr_ctorSetPaused( ctor, TR_FORCE, !pref_flag_get( PREF_KEY_START ) );
|
||||
|
||||
if( tr_ctorGetDeleteSource( ctor, NULL ) )
|
||||
tr_ctorSetDeleteSource( ctor, pref_flag_get( PREF_KEY_DELETE_ORIGINAL ) );
|
||||
|
||||
if( tr_ctorGetMaxConnectedPeers( ctor, TR_FORCE, NULL ) )
|
||||
tr_ctorSetMaxConnectedPeers( ctor, TR_FORCE, pref_int_get( PREF_KEY_MAX_PEERS_PER_TORRENT ) );
|
||||
|
||||
if( tr_ctorGetDestination( ctor, TR_FORCE, NULL ) ) {
|
||||
char * path = pref_string_get( PREF_KEY_DIR_DEFAULT );
|
||||
tr_ctorSetDestination( ctor, TR_FORCE, path );
|
||||
g_free( path );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
tr_core_add_ctor( TrCore * self, tr_ctor * ctor )
|
||||
{
|
||||
TrTorrent * tor;
|
||||
char * errstr;
|
||||
|
||||
TR_IS_CORE( self );
|
||||
|
||||
errstr = NULL;
|
||||
tor = tr_torrent_new( tr_core_handle( self ), path, dir, act, paused, &errstr );
|
||||
if( NULL == tor )
|
||||
|
||||
tr_core_apply_defaults( ctor );
|
||||
tor = tr_torrent_new_ctor( tr_core_handle( self ), ctor, &errstr );
|
||||
if( !tor )
|
||||
{
|
||||
tr_core_errsig( self, TR_CORE_ERR_ADD_TORRENT, errstr );
|
||||
g_free( errstr );
|
||||
return FALSE;
|
||||
errstr = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_assert( !errstr );
|
||||
tr_core_add_torrent( self, tor );
|
||||
}
|
||||
g_assert( NULL == errstr );
|
||||
|
||||
tr_core_insert( self, tor );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int
|
||||
tr_core_add_list( TrCore * self, GList * paths, enum tr_torrent_action act,
|
||||
gboolean paused )
|
||||
void
|
||||
tr_core_add_list( TrCore * self,
|
||||
GList * paths,
|
||||
tr_ctor * ctor )
|
||||
{
|
||||
char * dir;
|
||||
int count;
|
||||
tr_core_apply_defaults( ctor );
|
||||
|
||||
TR_IS_CORE( self );
|
||||
|
||||
if( pref_flag_get( PREF_KEY_DIR_ASK ) )
|
||||
if( pref_flag_get( PREF_KEY_OPTIONS_PROMPT ) )
|
||||
{
|
||||
TrCoreClass * class = g_type_class_peek( TR_CORE_TYPE );
|
||||
g_signal_emit( self, class->promptsig, 0, paths, act, paused );
|
||||
return 0;
|
||||
g_signal_emit( self, class->promptsig, 0, paths, ctor );
|
||||
}
|
||||
|
||||
dir = getdownloaddir();
|
||||
count = 0;
|
||||
for( ; paths; paths=paths->next )
|
||||
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 )
|
||||
{
|
||||
gboolean ret;
|
||||
char * path;
|
||||
TR_IS_CORE( self );
|
||||
|
||||
if( pref_flag_get( PREF_KEY_DIR_ASK ) )
|
||||
else
|
||||
{
|
||||
TrCoreClass * class = g_type_class_peek( TR_CORE_TYPE );
|
||||
g_signal_emit( self, class->promptdatasig, 0, data, size, paused );
|
||||
return FALSE;
|
||||
for( ; paths; paths=paths->next )
|
||||
if( !tr_ctorSetMetainfoFromFile( ctor, paths->data ) )
|
||||
tr_core_add_ctor( self, ctor );
|
||||
tr_ctorFree( ctor );
|
||||
}
|
||||
|
||||
path = getdownloaddir( );
|
||||
ret = tr_core_add_data_dir( self, data, size, path, paused );
|
||||
g_free( path );
|
||||
return ret;
|
||||
}
|
||||
|
||||
gboolean
|
||||
tr_core_add_data_dir( TrCore * self, uint8_t * data, size_t size,
|
||||
const char * dir, gboolean paused )
|
||||
{
|
||||
TrTorrent * tor;
|
||||
char * errstr = NULL;
|
||||
|
||||
TR_IS_CORE( self );
|
||||
|
||||
tor = tr_torrent_new_with_data( tr_core_handle( self ), data, size, dir,
|
||||
paused, &errstr );
|
||||
if( NULL == tor )
|
||||
{
|
||||
tr_core_errsig( self, TR_CORE_ERR_ADD_TORRENT, errstr );
|
||||
g_free( errstr );
|
||||
return FALSE;
|
||||
}
|
||||
g_assert( NULL == errstr );
|
||||
|
||||
tr_core_insert( self, tor );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
tr_core_torrents_added( TrCore * self )
|
||||
{
|
||||
TR_IS_CORE( self );
|
||||
|
||||
tr_core_update( self );
|
||||
tr_core_errsig( self, TR_CORE_ERR_NO_MORE_TORRENTS, NULL );
|
||||
}
|
||||
|
@ -672,8 +589,6 @@ tr_core_delete_torrent( TrCore * self, GtkTreeIter * iter )
|
|||
TrTorrent * tor;
|
||||
GtkTreeModel * model = tr_core_model( self );
|
||||
|
||||
TR_IS_CORE( self );
|
||||
|
||||
gtk_tree_model_get( model, iter, MC_TORRENT, &tor, -1 );
|
||||
gtk_list_store_remove( GTK_LIST_STORE( model ), iter );
|
||||
tr_torrentRemoveSaved( tr_torrent_handle( tor ) );
|
||||
|
@ -746,11 +661,7 @@ tr_core_update( TrCore * self )
|
|||
void
|
||||
tr_core_quit( TrCore * self )
|
||||
{
|
||||
TrCoreClass * class;
|
||||
|
||||
TR_IS_CORE( self );
|
||||
|
||||
class = g_type_class_peek( TR_CORE_TYPE );
|
||||
TrCoreClass * class = g_type_class_peek( TR_CORE_TYPE );
|
||||
g_signal_emit( self, class->quitsig, 0 );
|
||||
}
|
||||
|
||||
|
|
|
@ -30,28 +30,17 @@
|
|||
#include <glib-object.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include <libtransmission/bencode.h>
|
||||
#include <libtransmission/transmission.h>
|
||||
|
||||
#include "tr_torrent.h"
|
||||
#include "util.h"
|
||||
|
||||
#define TR_CORE_TYPE ( tr_core_get_type() )
|
||||
|
||||
#define TR_CORE( obj ) \
|
||||
( G_TYPE_CHECK_INSTANCE_CAST( (obj), TR_CORE_TYPE, TrCore ) )
|
||||
|
||||
#define TR_CORE_CLASS( class ) \
|
||||
( G_TYPE_CHECK_CLASS_CAST( (class), TR_CORE_TYPE, TrCoreClass ) )
|
||||
|
||||
#define TR_IS_CORE( obj ) \
|
||||
( G_TYPE_CHECK_INSTANCE_TYPE( (obj), TR_CORE_TYPE ) )
|
||||
|
||||
#define TR_IS_CORE_CLASS( class ) \
|
||||
( G_TYPE_CHECK_CLASS_TYPE( (class), TR_CORE_TYPE ) )
|
||||
|
||||
#define TR_CORE_GET_CLASS( obj ) \
|
||||
( G_TYPE_INSTANCE_GET_CLASS( (obj), TR_CORE_TYPE, TrCoreClass ) )
|
||||
|
||||
#define TR_CORE_TYPE (tr_core_get_type())
|
||||
#define TR_CORE(o) G_TYPE_CHECK_INSTANCE_CAST((o),TR_CORE_TYPE,TrCore)
|
||||
#define TR_IS_CORE(o) G_TYPE_CHECK_INSTANCE_TYPE((o),TR_CORE_TYPE)
|
||||
#define TR_CORE_CLASS(k) G_TYPE_CHECK_CLASS_CAST((k),TR_CORE_TYPE,TrCoreClass)
|
||||
#define TR_IS_CORE_CLASS(k) G_TYPE_CHECK_CLASS_TYPE((k),TR_CORE_TYPE)
|
||||
#define TR_CORE_GET_CLASS(o) G_TYPE_INSTANCE_GET_CLASS((o),TR_CORE_TYPE,TrCoreClass)
|
||||
|
||||
struct core_stats
|
||||
{
|
||||
|
@ -61,7 +50,6 @@ struct core_stats
|
|||
float clientUploadSpeed;
|
||||
};
|
||||
|
||||
/* treat the contents of this structure as private */
|
||||
typedef struct TrCore
|
||||
{
|
||||
GObject parent;
|
||||
|
@ -78,13 +66,9 @@ typedef struct TrCoreClass
|
|||
int errsig;
|
||||
|
||||
/* "directory-prompt" signal:
|
||||
void handler( TrCore *, GList *, enum tr_torrent_action, gboolean, gpointer ) */
|
||||
void handler( TrCore *, GList *, gpointer ctor, gpointer userData ) */
|
||||
int promptsig;
|
||||
|
||||
/* "directory-prompt-data" signal:
|
||||
void handler( TrCore *, uint8_t *, size_t, gboolean, gpointer ) */
|
||||
int promptdatasig;
|
||||
|
||||
/* "quit" signal:
|
||||
void handler( TrCore *, gpointer ) */
|
||||
int quitsig;
|
||||
|
@ -120,41 +104,45 @@ tr_core_handle( TrCore * self );
|
|||
const struct core_stats*
|
||||
tr_core_get_stats( const TrCore * self );
|
||||
|
||||
/* Load saved state, return number of torrents added. May trigger one
|
||||
or more "error" signals with TR_CORE_ERR_ADD_TORRENT */
|
||||
int
|
||||
tr_core_load( TrCore * self, gboolean forcepaused );
|
||||
/******
|
||||
*******
|
||||
******/
|
||||
|
||||
/* Any the tr_core_add functions below may trigger an "error" signal
|
||||
with TR_CORE_ERR_ADD_TORRENT */
|
||||
/**
|
||||
* Load saved state and return number of torrents added.
|
||||
* May trigger one or more "error" signals with TR_CORE_ERR_ADD_TORRENT
|
||||
*/
|
||||
int tr_core_load( TrCore * self, gboolean forcepaused );
|
||||
|
||||
/* Add the torrent at the given path */
|
||||
gboolean
|
||||
tr_core_add( TrCore * self, const char * path, enum tr_torrent_action act,
|
||||
gboolean paused );
|
||||
/**
|
||||
* Add a torrent.
|
||||
* May trigger an "error" signal with TR_CORE_ERR_ADD_TORRENT
|
||||
* Caller must free the ctor.
|
||||
*/
|
||||
void tr_core_add_ctor( TrCore * self, tr_ctor * ctor );
|
||||
|
||||
/* Add the torrent at the given path with the given download directory */
|
||||
gboolean
|
||||
tr_core_add_dir( TrCore * self, const char * path, const char * dir,
|
||||
enum tr_torrent_action act, gboolean paused );
|
||||
/**
|
||||
* Add a list of torrents.
|
||||
* May trigger one or more "error" signals with TR_CORE_ERR_ADD_TORRENT
|
||||
*/
|
||||
void tr_core_add_list( TrCore * self,
|
||||
GList * torrentFiles,
|
||||
tr_ctor * ctor );
|
||||
|
||||
/* Add a list of torrents with the given paths */
|
||||
int
|
||||
tr_core_add_list( TrCore * self, GList * paths, enum tr_torrent_action act,
|
||||
gboolean paused );
|
||||
/**
|
||||
* Add a torrent.
|
||||
*/
|
||||
void tr_core_add_torrent( TrCore*, TrTorrent* );
|
||||
|
||||
/* Add the torrent data in the given buffer */
|
||||
gboolean
|
||||
tr_core_add_data( TrCore * self, uint8_t * data, size_t size, gboolean paused );
|
||||
/**
|
||||
* Notifies listeners that torrents have been added.
|
||||
* This should be called after one or more tr_core_add*() calls.
|
||||
*/
|
||||
void tr_core_torrents_added( TrCore * self );
|
||||
|
||||
/* Add the torrent data in the given buffer with the given download directory */
|
||||
gboolean
|
||||
tr_core_add_data_dir( TrCore * self, uint8_t * data, size_t size,
|
||||
const char * dir, gboolean paused );
|
||||
|
||||
/* Save state, update model, and signal the end of a torrent cluster */
|
||||
void
|
||||
tr_core_torrents_added( TrCore * self );
|
||||
/******
|
||||
*******
|
||||
******/
|
||||
|
||||
/* remove a torrent, waiting for it to pause if necessary */
|
||||
void
|
||||
|
|
293
gtk/tr_prefs.c
293
gtk/tr_prefs.c
|
@ -42,7 +42,7 @@ tr_prefs_init_global( void )
|
|||
pref_flag_set_default ( PREF_KEY_UL_LIMIT_ENABLED, FALSE );
|
||||
pref_int_set_default ( PREF_KEY_UL_LIMIT, 50 );
|
||||
|
||||
pref_flag_set_default ( PREF_KEY_DIR_ASK, FALSE );
|
||||
pref_flag_set_default ( PREF_KEY_OPTIONS_PROMPT, TRUE );
|
||||
pref_string_set_default ( PREF_KEY_DIR_DEFAULT, g_get_home_dir() );
|
||||
|
||||
pref_int_set_default ( PREF_KEY_PORT, TR_DEFAULT_PORT );
|
||||
|
@ -53,15 +53,15 @@ tr_prefs_init_global( void )
|
|||
pref_flag_set_default ( PREF_KEY_ASKQUIT, TRUE );
|
||||
pref_flag_set_default ( PREF_KEY_ENCRYPTED_ONLY, FALSE );
|
||||
|
||||
pref_string_set_default ( PREF_KEY_ADDSTD, toractionname(TR_TOR_COPY) );
|
||||
pref_string_set_default ( PREF_KEY_ADDIPC, toractionname(TR_TOR_COPY) );
|
||||
|
||||
pref_int_set_default ( PREF_KEY_MSGLEVEL, TR_MSG_INF );
|
||||
|
||||
pref_string_set_default ( PREF_KEY_SORT_MODE, "sort-by-name" );
|
||||
pref_flag_set_default ( PREF_KEY_SORT_REVERSED, FALSE );
|
||||
pref_flag_set_default ( PREF_KEY_MINIMAL_VIEW, FALSE );
|
||||
|
||||
pref_flag_set_default ( PREF_KEY_START, TRUE );
|
||||
pref_flag_set_default ( PREF_KEY_DELETE_ORIGINAL, FALSE );
|
||||
|
||||
pref_save( NULL );
|
||||
}
|
||||
|
||||
|
@ -69,25 +69,6 @@ tr_prefs_init_global( void )
|
|||
***
|
||||
**/
|
||||
|
||||
int
|
||||
tr_prefs_get_action( const char * key )
|
||||
{
|
||||
char * val = pref_string_get( key );
|
||||
const int ret = toraddaction( val );
|
||||
g_free( val );
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
tr_prefs_set_action( const char * key, int action )
|
||||
{
|
||||
pref_string_set( key, toractionname(action) );
|
||||
}
|
||||
|
||||
/**
|
||||
***
|
||||
**/
|
||||
|
||||
#define PREFS_KEY "prefs-key"
|
||||
|
||||
static void
|
||||
|
@ -154,66 +135,12 @@ new_path_chooser_button( const char * key, gpointer core )
|
|||
return w;
|
||||
}
|
||||
|
||||
static void
|
||||
action_cb( GtkComboBox * w, gpointer core )
|
||||
{
|
||||
const char * key = g_object_get_data( G_OBJECT(w), PREFS_KEY );
|
||||
GtkTreeIter iter;
|
||||
if( gtk_combo_box_get_active_iter( GTK_COMBO_BOX(w), &iter ) )
|
||||
{
|
||||
int action;
|
||||
GtkTreeModel * model = gtk_combo_box_get_model( GTK_COMBO_BOX(w) );
|
||||
gtk_tree_model_get( model, &iter, 1, &action, -1 );
|
||||
tr_core_set_pref( core, key, toractionname(action) );
|
||||
}
|
||||
}
|
||||
|
||||
static GtkWidget*
|
||||
new_action_combo( const char * key, gpointer core )
|
||||
{
|
||||
const char * s;
|
||||
GtkTreeIter iter;
|
||||
GtkCellRenderer * rend;
|
||||
GtkListStore * model;
|
||||
GtkWidget * w;
|
||||
|
||||
model = gtk_list_store_new( 2, G_TYPE_STRING, G_TYPE_INT );
|
||||
|
||||
s = _("Use the torrent file where it is");
|
||||
gtk_list_store_append( model, &iter );
|
||||
gtk_list_store_set( model, &iter, 1, TR_TOR_LEAVE, 0, s, -1 );
|
||||
|
||||
s = _("Keep a copy of the torrent file");
|
||||
gtk_list_store_append( model, &iter );
|
||||
gtk_list_store_set( model, &iter, 1, TR_TOR_COPY, 0, s, -1 );
|
||||
|
||||
s = _("Keep a copy and remove the original");
|
||||
gtk_list_store_append( model, &iter );
|
||||
gtk_list_store_set( model, &iter, 1, TR_TOR_MOVE, 0, s, -1 );
|
||||
|
||||
w = gtk_combo_box_new_with_model( GTK_TREE_MODEL(model) );
|
||||
gtk_combo_box_set_active( GTK_COMBO_BOX(w), tr_prefs_get_action(key) );
|
||||
g_object_set_data_full( G_OBJECT(w), PREFS_KEY, g_strdup(key), g_free );
|
||||
rend = gtk_cell_renderer_text_new( );
|
||||
gtk_cell_layout_pack_start( GTK_CELL_LAYOUT(w), rend, TRUE );
|
||||
gtk_cell_layout_add_attribute( GTK_CELL_LAYOUT(w), rend, "text", 0 );
|
||||
g_signal_connect( w, "changed", G_CALLBACK(action_cb), core );
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
static void
|
||||
target_cb( GtkWidget * widget, gpointer target )
|
||||
{
|
||||
gtk_widget_set_sensitive( GTK_WIDGET(target), gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(widget) ) );
|
||||
}
|
||||
|
||||
static void
|
||||
target_invert_cb( GtkWidget * widget, gpointer target )
|
||||
{
|
||||
gtk_widget_set_sensitive( GTK_WIDGET(target), !gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(widget) ) );
|
||||
}
|
||||
|
||||
struct test_port_data
|
||||
{
|
||||
GtkWidget * label;
|
||||
|
@ -267,34 +194,102 @@ dialogDestroyed( gpointer alive, GObject * dialog UNUSED )
|
|||
*(gboolean*)alive = FALSE;
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
tr_prefs_dialog_new( GObject * core, GtkWindow * parent )
|
||||
static GtkWidget*
|
||||
generalPage( GObject * core )
|
||||
{
|
||||
int row = 0;
|
||||
const char * s;
|
||||
GtkWidget * t;
|
||||
GtkWidget * w;
|
||||
|
||||
t = hig_workarea_create ();
|
||||
|
||||
hig_workarea_add_section_title (t, &row, _("Windows"));
|
||||
|
||||
s = _("Show an icon in the system _tray");
|
||||
w = new_check_button( s, PREF_KEY_SYSTRAY, core );
|
||||
hig_workarea_add_wide_control( t, &row, w );
|
||||
|
||||
s = _("Confirm _quit");
|
||||
w = new_check_button( s, PREF_KEY_ASKQUIT, core );
|
||||
hig_workarea_add_wide_control( t, &row, w );
|
||||
|
||||
hig_workarea_finish (t, &row);
|
||||
return t;
|
||||
}
|
||||
|
||||
static GtkWidget*
|
||||
torrentPage( GObject * core )
|
||||
{
|
||||
int row = 0;
|
||||
const char * s;
|
||||
GtkWidget * t;
|
||||
GtkWidget * w;
|
||||
|
||||
t = hig_workarea_create ();
|
||||
|
||||
hig_workarea_add_section_title( t, &row, _( "Location" ) );
|
||||
|
||||
w = new_path_chooser_button( PREF_KEY_DIR_DEFAULT, core );
|
||||
hig_workarea_add_row( t, &row, _( "Default download location:" ), w, NULL );
|
||||
|
||||
hig_workarea_add_section_divider( t, &row );
|
||||
hig_workarea_add_section_title( t, &row, _( "Adding Torrents" ) );
|
||||
|
||||
s = _( "Show _options window" );
|
||||
w = new_check_button( s, PREF_KEY_OPTIONS_PROMPT, core );
|
||||
hig_workarea_add_wide_control( t, &row, w );
|
||||
|
||||
s = _( "_Start transfers when added" );
|
||||
w = new_check_button( s, PREF_KEY_START, core );
|
||||
hig_workarea_add_wide_control( t, &row, w );
|
||||
|
||||
s = _( "_Delete original torrent file" );
|
||||
w = new_check_button( s, PREF_KEY_DELETE_ORIGINAL, core );
|
||||
hig_workarea_add_wide_control( t, &row, w );
|
||||
|
||||
hig_workarea_finish (t, &row);
|
||||
return t;
|
||||
}
|
||||
|
||||
static GtkWidget*
|
||||
peerPage( GObject * core )
|
||||
{
|
||||
int row = 0;
|
||||
const char * s;
|
||||
GtkWidget * t;
|
||||
GtkWidget * w;
|
||||
|
||||
t = hig_workarea_create ();
|
||||
hig_workarea_add_section_title (t, &row, _("Options"));
|
||||
|
||||
s = _("Use peer _exchange if possible");
|
||||
w = new_check_button( s, PREF_KEY_PEX, core );
|
||||
hig_workarea_add_wide_control( t, &row, w );
|
||||
|
||||
s = _("_Ignore unencrypted peers");
|
||||
w = new_check_button( s, PREF_KEY_ENCRYPTED_ONLY, core );
|
||||
hig_workarea_add_wide_control( t, &row, w );
|
||||
|
||||
hig_workarea_add_section_divider( t, &row );
|
||||
hig_workarea_add_section_title( t, &row, _( "Limits" ) );
|
||||
|
||||
w = new_spin_button( PREF_KEY_MAX_PEERS_GLOBAL, core, 1, 3000, 5 );
|
||||
hig_workarea_add_row( t, &row, _( "Total max peers:" ), w, NULL );
|
||||
w = new_spin_button( PREF_KEY_MAX_PEERS_PER_TORRENT, core, 1, 300, 5 );
|
||||
hig_workarea_add_row( t, &row, _( "Per-torrent max peers:" ), w, NULL );
|
||||
|
||||
hig_workarea_finish (t, &row);
|
||||
return t;
|
||||
}
|
||||
|
||||
static GtkWidget*
|
||||
bandwidthPage( GObject * core )
|
||||
{
|
||||
int row = 0;
|
||||
const char * s;
|
||||
GtkWidget * t;
|
||||
GtkWidget * w, * w2;
|
||||
GtkWidget * l;
|
||||
GtkWidget * h;
|
||||
GtkWidget * d;
|
||||
GtkTooltips * tips;
|
||||
gboolean * alive;
|
||||
|
||||
alive = g_new( gboolean, 1 );
|
||||
*alive = TRUE;
|
||||
|
||||
tips = gtk_tooltips_new( );
|
||||
|
||||
d = gtk_dialog_new_with_buttons( _("Preferences"), parent,
|
||||
GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
|
||||
NULL );
|
||||
gtk_window_set_role( GTK_WINDOW(d), "transmission-preferences-dialog" );
|
||||
gtk_dialog_set_has_separator( GTK_DIALOG( d ), FALSE );
|
||||
gtk_container_set_border_width( GTK_CONTAINER( d ), GUI_PAD );
|
||||
g_object_weak_ref( G_OBJECT( d ), dialogDestroyed, alive );
|
||||
|
||||
g_signal_connect( d, "response", G_CALLBACK(response_cb), core );
|
||||
|
||||
t = hig_workarea_create ();
|
||||
|
||||
|
@ -314,33 +309,24 @@ tr_prefs_dialog_new( GObject * core, GtkWindow * parent )
|
|||
g_signal_connect( w, "toggled", G_CALLBACK(target_cb), w2 );
|
||||
hig_workarea_add_row_w( t, &row, w, w2, NULL );
|
||||
|
||||
hig_workarea_add_section_divider( t, &row );
|
||||
hig_workarea_add_section_title (t, &row, _("Downloads"));
|
||||
hig_workarea_finish (t, &row);
|
||||
return t;
|
||||
}
|
||||
|
||||
s = _("P_rompt for download directory");
|
||||
w = new_check_button( s, PREF_KEY_DIR_ASK, core );
|
||||
w2 = new_path_chooser_button( PREF_KEY_DIR_DEFAULT, core );
|
||||
gtk_widget_set_sensitive( GTK_WIDGET(w2), !pref_flag_get( PREF_KEY_DIR_ASK ) );
|
||||
g_signal_connect( w, "toggled", G_CALLBACK(target_invert_cb), w2 );
|
||||
hig_workarea_add_row_w( t, &row, w, w2, NULL );
|
||||
static GtkWidget*
|
||||
networkPage( GObject * core, gpointer alive )
|
||||
{
|
||||
int row = 0;
|
||||
const char * s;
|
||||
GtkWidget * t;
|
||||
GtkWidget * w, * w2;
|
||||
GtkWidget * l;
|
||||
GtkWidget * h;
|
||||
GtkTooltips * tips;
|
||||
|
||||
w = new_action_combo( PREF_KEY_ADDSTD, core );
|
||||
s = _("For torrents added _normally:");
|
||||
l = hig_workarea_add_row( t, &row, s, w, NULL );
|
||||
tips = gtk_tooltips_new( );
|
||||
|
||||
w = new_action_combo( PREF_KEY_ADDIPC, core );
|
||||
s = _("For torrents added from _command-line:");
|
||||
l = hig_workarea_add_row( t, &row, s, w, NULL );
|
||||
|
||||
hig_workarea_add_section_divider( t, &row );
|
||||
hig_workarea_add_section_title( t, &row, _( "Peer Connections" ) );
|
||||
|
||||
w = new_spin_button( PREF_KEY_MAX_PEERS_GLOBAL, core, 1, 3000, 5 );
|
||||
hig_workarea_add_row( t, &row, _( "Global maximum connected peers:" ), w, NULL );
|
||||
w = new_spin_button( PREF_KEY_MAX_PEERS_PER_TORRENT, core, 1, 300, 5 );
|
||||
hig_workarea_add_row( t, &row, _( "Maximum connected peers for new torrents:" ), w, NULL );
|
||||
|
||||
hig_workarea_add_section_divider( t, &row );
|
||||
t = hig_workarea_create ();
|
||||
hig_workarea_add_section_title (t, &row, _("Network"));
|
||||
|
||||
s = _("_Automatically map port" );
|
||||
|
@ -363,27 +349,46 @@ tr_prefs_dialog_new( GObject * core, GtkWindow * parent )
|
|||
g_signal_connect( w, "toggled", G_CALLBACK(toggled_cb), l );
|
||||
g_signal_connect( w2, "value-changed", G_CALLBACK(testing_port_cb), l );
|
||||
|
||||
hig_workarea_add_section_divider( t, &row );
|
||||
hig_workarea_add_section_title (t, &row, _("Options"));
|
||||
|
||||
s = _("Use peer _exchange if possible");
|
||||
w = new_check_button( s, PREF_KEY_PEX, core );
|
||||
hig_workarea_add_wide_control( t, &row, w );
|
||||
|
||||
s = _("_Ignore unencrypted peers");
|
||||
w = new_check_button( s, PREF_KEY_ENCRYPTED_ONLY, core );
|
||||
hig_workarea_add_wide_control( t, &row, w );
|
||||
|
||||
s = _("Show an icon in the system _tray");
|
||||
w = new_check_button( s, PREF_KEY_SYSTRAY, core );
|
||||
hig_workarea_add_wide_control( t, &row, w );
|
||||
|
||||
s = _("Confirm _quit");
|
||||
w = new_check_button( s, PREF_KEY_ASKQUIT, core );
|
||||
hig_workarea_add_wide_control( t, &row, w );
|
||||
|
||||
hig_workarea_finish (t, &row);
|
||||
gtk_box_pack_start_defaults( GTK_BOX(GTK_DIALOG(d)->vbox), t );
|
||||
return t;
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
tr_prefs_dialog_new( GObject * core, GtkWindow * parent )
|
||||
{
|
||||
GtkWidget * d;
|
||||
GtkWidget * n;
|
||||
GtkWidget * w;
|
||||
gboolean * alive;
|
||||
|
||||
alive = g_new( gboolean, 1 );
|
||||
*alive = TRUE;
|
||||
|
||||
d = gtk_dialog_new_with_buttons( _("Preferences"), parent,
|
||||
GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
|
||||
NULL );
|
||||
gtk_window_set_role( GTK_WINDOW(d), "transmission-preferences-dialog" );
|
||||
gtk_dialog_set_has_separator( GTK_DIALOG( d ), FALSE );
|
||||
gtk_container_set_border_width( GTK_CONTAINER( d ), GUI_PAD );
|
||||
g_object_weak_ref( G_OBJECT( d ), dialogDestroyed, alive );
|
||||
|
||||
n = gtk_notebook_new( );
|
||||
|
||||
w = torrentPage( core );
|
||||
gtk_notebook_append_page( GTK_NOTEBOOK( n ), w, gtk_label_new (_("Torrents")) );
|
||||
w = peerPage( core );
|
||||
gtk_notebook_append_page( GTK_NOTEBOOK( n ), w, gtk_label_new (_("Peers")) );
|
||||
w = bandwidthPage( core );
|
||||
gtk_notebook_append_page( GTK_NOTEBOOK( n ), w, gtk_label_new (_("Bandwidth")) );
|
||||
w = networkPage( core, alive );
|
||||
gtk_notebook_append_page( GTK_NOTEBOOK( n ), w, gtk_label_new (_("Network")) );
|
||||
w = generalPage( core );
|
||||
gtk_notebook_append_page( GTK_NOTEBOOK( n ), w, gtk_label_new (_("General")) );
|
||||
|
||||
|
||||
g_signal_connect( d, "response", G_CALLBACK(response_cb), core );
|
||||
gtk_box_pack_start_defaults( GTK_BOX(GTK_DIALOG(d)->vbox), n );
|
||||
gtk_widget_show_all( GTK_DIALOG(d)->vbox );
|
||||
return d;
|
||||
}
|
||||
|
|
|
@ -24,10 +24,10 @@ GtkWidget * tr_prefs_dialog_new( GObject * core, GtkWindow * parent );
|
|||
#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_OPTIONS_PROMPT "show-options-window"
|
||||
#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_START "start-added-torrents"
|
||||
#define PREF_KEY_DELETE_ORIGINAL "delete-original-torrent-files"
|
||||
#define PREF_KEY_PORT "listening-port"
|
||||
#define PREF_KEY_NAT "nat-traversal-enabled"
|
||||
#define PREF_KEY_PEX "pex-enabled"
|
||||
|
@ -48,7 +48,4 @@ GtkWidget * tr_prefs_dialog_new( GObject * core, GtkWindow * parent );
|
|||
|
||||
void tr_prefs_init_global( void );
|
||||
|
||||
int tr_prefs_get_action( const char * key );
|
||||
void tr_prefs_set_action( const char * key, int action );
|
||||
|
||||
#endif
|
||||
|
|
123
gtk/tr_torrent.c
123
gtk/tr_torrent.c
|
@ -38,7 +38,6 @@
|
|||
struct TrTorrentPrivate
|
||||
{
|
||||
tr_torrent * handle;
|
||||
char * delfile;
|
||||
gboolean seeding_cap_enabled;
|
||||
gdouble seeding_cap; /* ratio to stop seeding at */
|
||||
};
|
||||
|
@ -54,7 +53,6 @@ tr_torrent_init(GTypeInstance *instance, gpointer g_class UNUSED )
|
|||
TR_TORRENT_TYPE,
|
||||
struct TrTorrentPrivate );
|
||||
p->handle = NULL;
|
||||
p->delfile = NULL;
|
||||
p->seeding_cap = 2.0;
|
||||
|
||||
#ifdef REFDBG
|
||||
|
@ -71,35 +69,35 @@ isDisposed( const TrTorrent * self )
|
|||
static void
|
||||
tr_torrent_dispose( GObject * o )
|
||||
{
|
||||
GObjectClass * parent = g_type_class_peek(g_type_parent(TR_TORRENT_TYPE));
|
||||
GObjectClass * parent;
|
||||
TrTorrent * self = TR_TORRENT( o );
|
||||
|
||||
if( !isDisposed( self ) )
|
||||
{
|
||||
if( self->priv->handle )
|
||||
tr_torrentClose( self->priv->handle );
|
||||
g_free( self->priv->delfile );
|
||||
self->priv = NULL;
|
||||
}
|
||||
|
||||
/* chain up to the parent class */
|
||||
parent = g_type_class_peek(g_type_parent(TR_TORRENT_TYPE));
|
||||
parent->dispose( o );
|
||||
}
|
||||
|
||||
static void
|
||||
tr_torrent_class_init(gpointer g_class, gpointer g_class_data UNUSED )
|
||||
tr_torrent_class_init( gpointer g_class, gpointer g_class_data UNUSED )
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS(g_class);
|
||||
gobject_class->dispose = tr_torrent_dispose;
|
||||
g_type_class_add_private( g_class, sizeof(struct TrTorrentPrivate) );
|
||||
g_type_class_add_private( g_class, sizeof( struct TrTorrentPrivate ) );
|
||||
}
|
||||
|
||||
GType
|
||||
tr_torrent_get_type(void)
|
||||
tr_torrent_get_type( void )
|
||||
{
|
||||
static GType type = 0;
|
||||
|
||||
if(0 == type) {
|
||||
if( !type )
|
||||
{
|
||||
static const GTypeInfo info = {
|
||||
sizeof (TrTorrentClass),
|
||||
NULL, /* base_init */
|
||||
|
@ -170,90 +168,41 @@ tr_torrent_new_preexisting( tr_torrent * tor )
|
|||
}
|
||||
|
||||
TrTorrent *
|
||||
tr_torrent_new( tr_handle * handle,
|
||||
const char * metainfo_filename,
|
||||
const char * destination,
|
||||
enum tr_torrent_action act,
|
||||
gboolean paused,
|
||||
char ** err )
|
||||
tr_torrent_new_ctor( tr_handle * handle,
|
||||
tr_ctor * ctor,
|
||||
char ** err )
|
||||
{
|
||||
TrTorrent * ret;
|
||||
tr_torrent * tor;
|
||||
tr_ctor * ctor;
|
||||
int errcode = -1;
|
||||
tr_torrent * tor;
|
||||
int errcode;
|
||||
|
||||
g_assert( destination );
|
||||
errcode = -1;
|
||||
*err = NULL;
|
||||
|
||||
*err = NULL;
|
||||
|
||||
ctor = tr_ctorNew( handle );
|
||||
tr_ctorSetMetainfoFromFile( ctor, metainfo_filename );
|
||||
tr_ctorSetDestination( ctor, TR_FORCE, destination );
|
||||
tr_ctorSetPaused( ctor, TR_FORCE, paused );
|
||||
tr_ctorSetMaxConnectedPeers( ctor, TR_FORCE, pref_int_get( PREF_KEY_MAX_PEERS_PER_TORRENT ) );
|
||||
tor = tr_torrentNew( handle, ctor, &errcode );
|
||||
tr_ctorFree( ctor );
|
||||
tor = tr_torrentNew( handle, ctor, &errcode );
|
||||
|
||||
if( tor == NULL ) {
|
||||
switch( errcode ) {
|
||||
case TR_EINVALID:
|
||||
*err = g_strdup_printf(_("%s: not a valid torrent file"), metainfo_filename );
|
||||
break;
|
||||
case TR_EDUPLICATE:
|
||||
*err = g_strdup_printf(_("%s: torrent is already open"), metainfo_filename );
|
||||
break;
|
||||
default:
|
||||
*err = g_strdup( metainfo_filename );
|
||||
break;
|
||||
if( !tor )
|
||||
{
|
||||
const char * filename = tr_ctorGetSourceFile( ctor );
|
||||
if( !filename )
|
||||
filename = "(null)";
|
||||
|
||||
switch( errcode )
|
||||
{
|
||||
case TR_EINVALID:
|
||||
*err = g_strdup_printf( _("%s: not a valid torrent file"), filename );
|
||||
break;
|
||||
case TR_EDUPLICATE:
|
||||
*err = g_strdup_printf( _("%s: torrent is already open"), filename );
|
||||
break;
|
||||
default:
|
||||
*err = g_strdup( filename );
|
||||
break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = maketorrent( tor );
|
||||
if( TR_TOR_MOVE == act )
|
||||
ret->priv->delfile = g_strdup( metainfo_filename );
|
||||
return ret;
|
||||
}
|
||||
|
||||
TrTorrent *
|
||||
tr_torrent_new_with_data( tr_handle * handle,
|
||||
uint8_t * metainfo,
|
||||
size_t size,
|
||||
const char * destination,
|
||||
gboolean paused,
|
||||
char ** err )
|
||||
{
|
||||
tr_torrent * tor;
|
||||
tr_ctor * ctor;
|
||||
int errcode = -1;
|
||||
|
||||
g_assert( destination );
|
||||
|
||||
*err = NULL;
|
||||
|
||||
ctor = tr_ctorNew( handle );
|
||||
tr_ctorSetMetainfo( ctor, metainfo, size );
|
||||
tr_ctorSetDestination( ctor, TR_FORCE, destination );
|
||||
tr_ctorSetPaused( ctor, TR_FORCE, paused );
|
||||
tr_ctorSetMaxConnectedPeers( ctor, TR_FORCE, pref_int_get( PREF_KEY_MAX_PEERS_PER_TORRENT ) );
|
||||
tor = tr_torrentNew( handle, ctor, &errcode );
|
||||
|
||||
if( tor == NULL ) {
|
||||
switch( errcode ) {
|
||||
case TR_EINVALID:
|
||||
*err = g_strdup( _("not a valid torrent file") );
|
||||
break;
|
||||
case TR_EDUPLICATE:
|
||||
*err = g_strdup( _("torrent is already open") );
|
||||
break;
|
||||
default:
|
||||
*err = g_strdup( "" );
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return maketorrent( tor );
|
||||
return maketorrent( tor );
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -87,11 +87,6 @@ TrTorrent *
|
|||
tr_torrent_new_preexisting( tr_torrent * tor );
|
||||
|
||||
TrTorrent *
|
||||
tr_torrent_new( tr_handle * handle, const char * path, const char * dir,
|
||||
enum tr_torrent_action act, gboolean paused, char ** err);
|
||||
|
||||
TrTorrent *
|
||||
tr_torrent_new_with_data( tr_handle * handle, uint8_t * data, size_t size,
|
||||
const char * dir, gboolean paused, char ** err );
|
||||
tr_torrent_new_ctor( tr_handle * handle, tr_ctor * ctor, char ** err );
|
||||
|
||||
#endif
|
||||
|
|
28
gtk/util.c
28
gtk/util.c
|
@ -222,34 +222,6 @@ checkfilenames( int argc, char **argv )
|
|||
return ret;
|
||||
}
|
||||
|
||||
enum tr_torrent_action
|
||||
toraddaction( const char * action )
|
||||
{
|
||||
if( !action || !strcmp( "copy", action ) )
|
||||
return TR_TOR_COPY;
|
||||
|
||||
if( !strcmp( "move", action ) )
|
||||
return TR_TOR_MOVE;
|
||||
|
||||
return TR_TOR_LEAVE;
|
||||
}
|
||||
|
||||
const char *
|
||||
toractionname( enum tr_torrent_action action )
|
||||
{
|
||||
switch( action )
|
||||
{
|
||||
case TR_TOR_COPY:
|
||||
return "copy";
|
||||
|
||||
case TR_TOR_MOVE:
|
||||
return "move";
|
||||
|
||||
default:
|
||||
return "leave";
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
getdownloaddir( void )
|
||||
{
|
||||
|
|
11
gtk/util.h
11
gtk/util.h
|
@ -34,9 +34,6 @@
|
|||
/* NULL-safe version of strcmp */
|
||||
int tr_strcmp( const char*, const char * );
|
||||
|
||||
/* XXX this shouldn't be here */
|
||||
enum tr_torrent_action { TR_TOR_LEAVE, TR_TOR_COPY, TR_TOR_MOVE };
|
||||
|
||||
/* return number of items in array */
|
||||
#define ALEN(a) ((signed)G_N_ELEMENTS(a))
|
||||
|
||||
|
@ -82,14 +79,6 @@ decode_uri( const char * uri );
|
|||
GList *
|
||||
checkfilenames( int argc, char ** argv );
|
||||
|
||||
/* returns the flag for an action string */
|
||||
enum tr_torrent_action
|
||||
toraddaction( const char * action );
|
||||
|
||||
/* returns the action string for a flag */
|
||||
const char *
|
||||
toractionname( enum tr_torrent_action action );
|
||||
|
||||
/* retrieve the global download directory */
|
||||
char *
|
||||
getdownloaddir( void );
|
||||
|
|
|
@ -3,12 +3,14 @@ gtk/transmission.desktop.in
|
|||
gtk/actions.c
|
||||
gtk/conf.c
|
||||
gtk/dialogs.c
|
||||
gtk/file-list.c
|
||||
gtk/hig.c
|
||||
gtk/io.c
|
||||
gtk/ipc.c
|
||||
gtk/main.c
|
||||
gtk/makemeta-ui.c
|
||||
gtk/msgwin.c
|
||||
gtk/open.c
|
||||
gtk/stats.c
|
||||
gtk/torrent-cell-renderer.c
|
||||
gtk/torrent-inspector.c
|
||||
|
|
Loading…
Reference in New Issue