source: trunk/gtk/dialogs.c @ 5207

Last change on this file since 5207 was 5207, checked in by charles, 14 years ago

(gtk) minor: use "Folder" instead of "Directory", as per the GNOME Desktop Terms list

  • Property svn:keywords set to Date Rev Author Id
File size: 13.1 KB
Line 
1/******************************************************************************
2 * $Id: dialogs.c 5207 2008-03-06 20:55:07Z charles $
3 *
4 * Copyright (c) 2005-2008 Transmission authors and contributors
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *****************************************************************************/
24
25#include <gtk/gtk.h>
26#include <glib/gi18n.h>
27
28#include <libtransmission/transmission.h>
29
30#include "conf.h"
31#include "dialogs.h"
32#include "hig.h"
33#include "tr-core.h"
34#include "tr-prefs.h"
35
36struct dirdata
37{
38    GtkWidget  * widget;
39    TrCore     * core;
40    GList      * files;
41    tr_ctor    * ctor;
42};
43
44static void
45promptdirnocore( gpointer gdata, GObject * core UNUSED )
46{
47    struct dirdata * stuff = gdata;
48
49    /* prevent the response callback from trying to remove the weak
50       reference which no longer exists */
51    stuff->core = NULL;
52
53    gtk_dialog_response( GTK_DIALOG( stuff->widget ), GTK_RESPONSE_NONE );
54}
55
56static void
57promptresp( GtkWidget * widget, gint resp, gpointer data )
58{
59    struct dirdata * stuff;
60
61    stuff = data;
62
63    if( GTK_RESPONSE_ACCEPT == resp )
64    {
65        char * dir;
66        GList * l;
67
68        /* update the destination */
69        dir = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER( widget ) );
70        tr_ctorSetDestination( stuff->ctor, TR_FORCE, dir );
71        g_free( dir );
72
73        /* if there's metainfo in the ctor already, use it */
74        if( !tr_ctorGetMetainfo( stuff->ctor, NULL ) )
75            tr_core_add_ctor( stuff->core, stuff->ctor );
76
77        /* if there's a list of files, use them too */
78        for( l=stuff->files; l!=NULL; l=l->next )
79            if( !tr_ctorSetMetainfoFromFile( stuff->ctor, l->data ) )
80                tr_core_add_ctor( stuff->core, stuff->ctor );
81    }
82
83    if( stuff->core )
84        g_object_weak_unref( G_OBJECT( stuff->core ), promptdirnocore, stuff );
85
86    gtk_widget_destroy( widget );
87    freestrlist( stuff->files );
88    tr_ctorFree( stuff->ctor );
89    g_free( stuff );
90}
91
92void
93fmtpeercount( GtkLabel * label, int count )
94{
95    char str[16];
96
97    if( 0 > count )
98    {
99        gtk_label_set_text( label, "?" );
100    }
101    else
102    {
103        g_snprintf( str, sizeof str, "%i", count );
104        gtk_label_set_text( label, str );
105    }
106}
107
108static void
109deleteToggled( GtkToggleButton * tb, gpointer ctor )
110{
111    tr_ctorSetDeleteSource( ctor, gtk_toggle_button_get_active( tb ) );
112}
113
114static void
115startToggled( GtkToggleButton * tb, gpointer ctor )
116{
117    tr_ctorSetPaused( ctor, TR_FORCE, !gtk_toggle_button_get_active( tb ) );
118}
119
120GtkWidget*
121promptfordir( GtkWindow * parent, TrCore * core, GList * files, tr_ctor * ctor )
122{
123    uint8_t          flag = 0;
124    const char     * str;
125    struct dirdata * stuff;
126    GtkWidget      * wind;
127    GtkWidget      * v;
128    GtkWidget      * w;
129
130    stuff = g_new0( struct dirdata, 1 );
131    stuff->core   = core;
132    stuff->ctor   = ctor;
133    stuff->files  = dupstrlist( files );
134
135    g_object_weak_ref( G_OBJECT( core ), promptdirnocore, stuff );
136
137    wind =  gtk_file_chooser_dialog_new( _("Destination folder"), parent,
138                                         GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
139                                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
140                                         GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
141                                         NULL );
142    gtk_dialog_set_alternative_button_order( GTK_DIALOG( wind ),
143                                             GTK_RESPONSE_ACCEPT,
144                                             GTK_RESPONSE_CANCEL,
145                                             -1 );
146    gtk_file_chooser_set_local_only( GTK_FILE_CHOOSER( wind ), TRUE );
147    gtk_file_chooser_set_select_multiple( GTK_FILE_CHOOSER( wind ), FALSE );
148    if( tr_ctorGetDestination( ctor, TR_FORCE, &str ) )
149        g_assert_not_reached( );
150    if( !gtk_file_chooser_set_filename( GTK_FILE_CHOOSER( wind ), str ) )
151        g_warning( "couldn't set destination '%s'", str );
152
153    v = gtk_vbox_new( FALSE, GUI_PAD );
154
155        flag = 0;
156        w = gtk_check_button_new_with_mnemonic( _( "_Delete original torrent file" ) );
157        g_signal_connect( w, "toggled", G_CALLBACK( deleteToggled ), ctor );
158        if( tr_ctorGetDeleteSource( ctor, &flag ) )
159            g_assert_not_reached( );
160        gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( w ), flag );
161        gtk_box_pack_start( GTK_BOX( v ), w, FALSE, FALSE, 0 );
162
163        flag = 1;
164        w = gtk_check_button_new_with_mnemonic( _( "_Start when added" ) );
165        g_signal_connect( w, "toggled", G_CALLBACK( startToggled ), ctor );
166        if( tr_ctorGetPaused( ctor, TR_FORCE, &flag ) )
167            g_assert_not_reached( );
168        gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( w ), !flag );
169        gtk_box_pack_start( GTK_BOX( v ), w, FALSE, FALSE, 0 );
170
171    gtk_file_chooser_set_extra_widget( GTK_FILE_CHOOSER( wind ), v );
172
173    stuff->widget = wind;
174
175    g_signal_connect( G_OBJECT( wind ), "response",
176                      G_CALLBACK( promptresp ), stuff );
177
178    gtk_widget_show_all( wind );
179    return wind;
180}
181
182/***
183****
184***/
185
186struct quitdata
187{
188    TrCore          * core;
189    callbackfunc_t    func;
190    void            * cbdata;
191    GtkWidget       * dontask;
192};
193
194static void
195quitresp( GtkWidget * widget, int response, gpointer data )
196{
197    struct quitdata * stuff = data;
198    GtkToggleButton * tb = GTK_TOGGLE_BUTTON( stuff->dontask );
199
200    tr_core_set_pref_bool( stuff->core,
201                           PREF_KEY_ASKQUIT,
202                           !gtk_toggle_button_get_active( tb ) );
203
204    if( response == GTK_RESPONSE_ACCEPT )
205        stuff->func( stuff->cbdata );
206
207    g_free( stuff );
208    gtk_widget_destroy( widget );
209}
210
211static gboolean
212countActiveTorrents( GtkTreeModel  * model,
213                     GtkTreePath   * path UNUSED,
214                     GtkTreeIter   * iter,
215                     gpointer        activeTorrentCount )
216{
217    int status = -1;
218    gtk_tree_model_get( model, iter, MC_STATUS, &status, -1 );
219    if( status != TR_STATUS_STOPPED )
220        *(int*)activeTorrentCount += 1;
221    return FALSE; /* keep iterating */
222}
223
224void
225askquit( TrCore          * core,
226         GtkWindow       * parent,
227         callbackfunc_t    func,
228         void            * cbdata )
229{
230    struct quitdata * stuff;
231    GtkWidget * wind;
232    GtkWidget * dontask;
233    GtkTreeModel * model;
234    int activeTorrentCount;
235
236    /* if the user doesn't want to be asked, don't ask */
237    if( !pref_flag_get( PREF_KEY_ASKQUIT ) ) {
238        func( cbdata );
239        return;
240    }
241
242    /* if there aren't any active torrents, don't ask */
243    model = tr_core_model( core );
244    activeTorrentCount = 0;
245    gtk_tree_model_foreach( model, countActiveTorrents, &activeTorrentCount );
246    if( !activeTorrentCount ) {
247        func( cbdata );
248        return;
249    }
250
251    stuff          = g_new( struct quitdata, 1 );
252    stuff->func    = func;
253    stuff->cbdata  = cbdata;
254    stuff->core    = core;
255
256    wind = gtk_message_dialog_new_with_markup( parent,
257                                               GTK_DIALOG_DESTROY_WITH_PARENT,
258                                               GTK_MESSAGE_QUESTION,
259                                               GTK_BUTTONS_NONE,
260                                               _("<b>Really Quit %s?</b>"),
261                                               g_get_application_name() );
262
263    gtk_message_dialog_format_secondary_text( GTK_MESSAGE_DIALOG(wind),
264                                              _("This will close all active torrents."));
265    gtk_dialog_add_buttons( GTK_DIALOG(wind),
266                            GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
267                            GTK_STOCK_QUIT, GTK_RESPONSE_ACCEPT,
268                            NULL );
269    gtk_dialog_set_default_response( GTK_DIALOG( wind ),
270                                     GTK_RESPONSE_ACCEPT );
271    gtk_dialog_set_alternative_button_order( GTK_DIALOG( wind ),
272                                     GTK_RESPONSE_ACCEPT,
273                                     GTK_RESPONSE_CANCEL );
274
275    dontask = gtk_check_button_new_with_mnemonic( _("_Don't Ask Me This Again") );
276    stuff->dontask = dontask;
277
278    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(wind)->vbox), dontask, FALSE, FALSE, GUI_PAD );
279
280    g_signal_connect( G_OBJECT( wind ), "response",
281                      G_CALLBACK( quitresp ), stuff );
282
283    gtk_widget_show_all( wind );
284}
285
286/***
287****
288***/
289
290struct DeleteData
291{
292    gboolean delete_files;
293    GList * torrents;
294    TrCore * core;
295};
296
297static void
298removeResponse( GtkDialog * dialog, gint response, gpointer gdata )
299{
300    struct DeleteData * data = gdata;
301    const int doRemove = response == GTK_RESPONSE_ACCEPT;
302    const int doDelete = data->delete_files;
303    GList * l;
304
305    for( l=data->torrents; l!=NULL; l=l->next )
306    {
307        TrTorrent * gtor = TR_TORRENT( l->data );
308
309        if( doRemove )
310            tr_core_remove_torrent( data->core, gtor, doDelete );
311        else
312            g_object_unref( G_OBJECT( gtor ) );
313    }
314
315    gtk_widget_destroy( GTK_WIDGET( dialog ) );
316    g_list_free( data->torrents );
317    g_free( data );
318}
319
320void
321confirmRemove( GtkWindow * parent,
322               TrCore    * core,
323               GList     * torrents )
324{
325    GtkWidget * d;
326    char text[128];
327    struct DeleteData * dd = g_new0( struct DeleteData, 1 );
328
329    dd->core = core;
330    dd->torrents = torrents;
331    dd->delete_files = FALSE;
332
333    g_snprintf( text, sizeof( text ),
334                ngettext( "Remove torrent?",
335                          "Remove torrents?",
336                          g_list_length( torrents ) ) );
337    d = gtk_message_dialog_new_with_markup( parent,
338                                            GTK_DIALOG_DESTROY_WITH_PARENT,
339                                            GTK_MESSAGE_QUESTION,
340                                            GTK_BUTTONS_NONE,
341                                            "<b>%s</b>", text );
342    gtk_message_dialog_format_secondary_text( GTK_MESSAGE_DIALOG( d ),
343                   _( "This removes the torrent, not the downloaded files." ) );
344    gtk_dialog_add_buttons( GTK_DIALOG( d ),
345                            GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
346                            GTK_STOCK_REMOVE, GTK_RESPONSE_ACCEPT,
347                            NULL );
348    gtk_dialog_set_default_response( GTK_DIALOG ( d ),
349                                     GTK_RESPONSE_ACCEPT );
350    gtk_dialog_set_alternative_button_order( GTK_DIALOG( d ),
351                                             GTK_RESPONSE_ACCEPT,
352                                             GTK_RESPONSE_CANCEL,
353                                             -1 );
354    g_signal_connect( d, "response", G_CALLBACK( removeResponse ), dd );
355    gtk_widget_show_all( d );
356}
357
358void
359confirmDelete( GtkWindow * parent,
360               TrCore    * core,
361               GList     * torrents )
362{
363    GtkWidget * d;
364    char text[128];
365    struct DeleteData * dd = g_new0( struct DeleteData, 1 );
366
367    dd->core = core;
368    dd->torrents = torrents;
369    dd->delete_files = TRUE;
370
371    g_snprintf( text, sizeof( text ),
372                ngettext( "Delete torrent?",
373                          "Delete torrents?",
374                          g_list_length( torrents ) ) );
375    d = gtk_message_dialog_new_with_markup( parent,
376                                            GTK_DIALOG_DESTROY_WITH_PARENT,
377                                            GTK_MESSAGE_WARNING,
378                                            GTK_BUTTONS_NONE,
379                                            "<b>%s</b>", text );
380    gtk_message_dialog_format_secondary_text( GTK_MESSAGE_DIALOG( d ),
381            _( "This removes the torrent and deletes the downloaded files!" ) );
382    gtk_dialog_add_buttons( GTK_DIALOG( d ),
383                            GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
384                            GTK_STOCK_DELETE, GTK_RESPONSE_ACCEPT,
385                            NULL );
386    gtk_dialog_set_default_response( GTK_DIALOG ( d ),
387                                     GTK_RESPONSE_CANCEL );
388    gtk_dialog_set_alternative_button_order( GTK_DIALOG( d ),
389                                             GTK_RESPONSE_ACCEPT,
390                                             GTK_RESPONSE_CANCEL,
391                                             -1 );
392    g_signal_connect( d, "response", G_CALLBACK( removeResponse ), dd );
393    gtk_widget_show_all( d );
394}
Note: See TracBrowser for help on using the repository browser.