source: trunk/gtk/dialogs.c @ 5636

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

fix a couple more minor leaks

  • Property svn:keywords set to Date Rev Author Id
File size: 8.0 KB
Line 
1/******************************************************************************
2 * $Id: dialogs.c 5636 2008-04-17 19:54:22Z 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
36/***
37****
38***/
39
40struct quitdata
41{
42    TrCore          * core;
43    callbackfunc_t    func;
44    void            * cbdata;
45    GtkWidget       * dontask;
46};
47
48static void
49quitresp( GtkWidget * widget, int response, gpointer data )
50{
51    struct quitdata * stuff = data;
52    GtkToggleButton * tb = GTK_TOGGLE_BUTTON( stuff->dontask );
53
54    tr_core_set_pref_bool( stuff->core,
55                           PREF_KEY_ASKQUIT,
56                           !gtk_toggle_button_get_active( tb ) );
57
58    if( response == GTK_RESPONSE_ACCEPT )
59        stuff->func( stuff->cbdata );
60
61    g_free( stuff );
62    gtk_widget_destroy( widget );
63}
64
65static gboolean
66countActiveTorrents( GtkTreeModel  * model,
67                     GtkTreePath   * path UNUSED,
68                     GtkTreeIter   * iter,
69                     gpointer        activeTorrentCount )
70{
71    int status = -1;
72    gtk_tree_model_get( model, iter, MC_STATUS, &status, -1 );
73    if( status != TR_STATUS_STOPPED )
74        *(int*)activeTorrentCount += 1;
75    return FALSE; /* keep iterating */
76}
77
78void
79askquit( TrCore          * core,
80         GtkWindow       * parent,
81         callbackfunc_t    func,
82         void            * cbdata )
83{
84    struct quitdata * stuff;
85    GtkWidget * wind;
86    GtkWidget * dontask;
87    GtkTreeModel * model;
88    int activeTorrentCount;
89
90    /* if the user doesn't want to be asked, don't ask */
91    if( !pref_flag_get( PREF_KEY_ASKQUIT ) ) {
92        func( cbdata );
93        return;
94    }
95
96    /* if there aren't any active torrents, don't ask */
97    model = tr_core_model( core );
98    activeTorrentCount = 0;
99    gtk_tree_model_foreach( model, countActiveTorrents, &activeTorrentCount );
100    if( !activeTorrentCount ) {
101        func( cbdata );
102        return;
103    }
104
105    stuff          = g_new( struct quitdata, 1 );
106    stuff->func    = func;
107    stuff->cbdata  = cbdata;
108    stuff->core    = core;
109
110    wind = gtk_message_dialog_new_with_markup( parent,
111                                               GTK_DIALOG_DESTROY_WITH_PARENT,
112                                               GTK_MESSAGE_WARNING,
113                                               GTK_BUTTONS_NONE,
114                                               _("<big><b>Quit Transmission?</b></big>") );
115
116    gtk_dialog_add_buttons( GTK_DIALOG(wind),
117                            GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
118                            GTK_STOCK_QUIT, GTK_RESPONSE_ACCEPT,
119                            NULL );
120    gtk_dialog_set_default_response( GTK_DIALOG( wind ),
121                                     GTK_RESPONSE_ACCEPT );
122    gtk_dialog_set_alternative_button_order( GTK_DIALOG( wind ),
123                                     GTK_RESPONSE_ACCEPT,
124                                     GTK_RESPONSE_CANCEL );
125
126    dontask = gtk_check_button_new_with_mnemonic( _("_Don't ask me again") );
127    stuff->dontask = dontask;
128
129    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(wind)->vbox), dontask, FALSE, FALSE, GUI_PAD );
130
131    g_signal_connect( G_OBJECT( wind ), "response",
132                      G_CALLBACK( quitresp ), stuff );
133
134    gtk_widget_show_all( wind );
135}
136
137/***
138****
139***/
140
141struct DeleteData
142{
143    gboolean delete_files;
144    GSList * torrents;
145    TrCore * core;
146};
147
148static void
149removeTorrents( struct DeleteData * data )
150{
151    GSList * l;
152    for( l=data->torrents; l!=NULL; l=l->next )
153        tr_core_remove_torrent( data->core, l->data, data->delete_files );
154    g_slist_free( data->torrents );
155    data->torrents = NULL;
156}
157
158
159static void
160removeResponse( GtkDialog * dialog, gint response, gpointer gdata )
161{
162    struct DeleteData * data = gdata;
163
164    if( response == GTK_RESPONSE_ACCEPT )
165        removeTorrents( data );
166    else
167        g_slist_foreach( data->torrents, (GFunc)g_object_unref, NULL );
168
169    gtk_widget_destroy( GTK_WIDGET( dialog ) );
170    g_slist_free( data->torrents );
171    g_free( data );
172}
173
174static void
175countBusyTorrents( gpointer gtor, gpointer busyCount )
176{
177    const tr_stat * stat = tr_torrent_stat( gtor );
178
179    if( stat->leftUntilDone || stat->peersConnected )
180        ++(*(int*)busyCount);
181}
182
183void
184confirmRemove( GtkWindow * parent,
185               TrCore    * core,
186               GSList    * torrents,
187               gboolean    delete_files )
188{
189    GtkWidget * d;
190    struct DeleteData * dd;
191    int busyCount;
192    const int count = g_slist_length( torrents );
193    const char * primary_text;
194    const char * secondary_text;
195
196    if( !count )
197        return;
198
199    dd = g_new0( struct DeleteData, 1 );
200    dd->core = core;
201    dd->torrents = torrents;
202    dd->delete_files = delete_files;
203
204    busyCount = 0;
205    g_slist_foreach( torrents, countBusyTorrents, &busyCount );
206
207    if( !busyCount && !delete_files ) /* don't prompt boring torrents */
208    {
209        removeTorrents( dd );
210        g_free( dd );
211        return;
212    }
213
214    if( !delete_files )
215        primary_text = ngettext( "Remove torrent?", "Remove torrents?", count );
216    else
217        primary_text = ngettext( "Delete this torrent's downloaded files?",
218                                 "Delete these torrents' downloaded files?",
219                                 count );
220
221    if( busyCount > 1 )
222        secondary_text = _( "Some of these torrents are incomplete or connected to peers." );
223    else if( busyCount == 0 )
224        secondary_text = NULL;
225    else
226        secondary_text = ngettext( "This torrent is incomplete or connected to peers.",
227                                   "One of these torrents is incomplete or connected to peers.",
228                                   count );
229
230    d = gtk_message_dialog_new_with_markup( parent,
231                                            GTK_DIALOG_DESTROY_WITH_PARENT,
232                                            GTK_MESSAGE_WARNING,
233                                            GTK_BUTTONS_NONE,
234                                            "<big><b>%s</b></big>", primary_text );
235    if( secondary_text )
236        gtk_message_dialog_format_secondary_markup( GTK_MESSAGE_DIALOG( d ), secondary_text );
237    gtk_dialog_add_buttons( GTK_DIALOG( d ),
238                            GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
239                            (delete_files ? GTK_STOCK_DELETE : GTK_STOCK_REMOVE), GTK_RESPONSE_ACCEPT,
240                            NULL );
241    gtk_dialog_set_default_response( GTK_DIALOG ( d ),
242                                     GTK_RESPONSE_CANCEL );
243    gtk_dialog_set_alternative_button_order( GTK_DIALOG( d ),
244                                             GTK_RESPONSE_ACCEPT,
245                                             GTK_RESPONSE_CANCEL,
246                                             -1 );
247    g_signal_connect( d, "response", G_CALLBACK( removeResponse ), dd );
248    gtk_widget_show_all( d );
249}
Note: See TracBrowser for help on using the repository browser.