source: trunk/gtk/dialogs.c @ 8889

Last change on this file since 8889 was 8889, checked in by charles, 12 years ago

(trunk) remove trailing spaces

  • Property svn:keywords set to Date Rev Author Id
File size: 9.8 KB
Line 
1/******************************************************************************
2 * $Id: dialogs.c 8889 2009-08-10 20:04:08Z 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,
50          int         response,
51          gpointer    data )
52{
53    struct quitdata * stuff = data;
54    GtkToggleButton * tb = GTK_TOGGLE_BUTTON( stuff->dontask );
55
56    tr_core_set_pref_bool( stuff->core,
57                          PREF_KEY_ASKQUIT,
58                          !gtk_toggle_button_get_active( tb ) );
59
60    if( response == GTK_RESPONSE_ACCEPT )
61        stuff->func( stuff->cbdata );
62
63    g_free( stuff );
64    gtk_widget_destroy( widget );
65}
66
67static gboolean
68countActiveTorrents( GtkTreeModel *       model,
69                     GtkTreePath   * path UNUSED,
70                     GtkTreeIter *        iter,
71                     gpointer             activeTorrentCount )
72{
73    int activity = -1;
74    gtk_tree_model_get( model, iter, MC_ACTIVITY, &activity, -1 );
75    if( activity != TR_STATUS_STOPPED )
76        *(int*)activeTorrentCount += 1;
77    return FALSE; /* keep iterating */
78}
79
80void
81askquit( TrCore *       core,
82         GtkWindow *    parent,
83         callbackfunc_t func,
84         void *         cbdata )
85{
86    struct quitdata * stuff;
87    GtkWidget *       w;
88    GtkWidget *       wind;
89    GtkWidget *       dontask;
90    GtkTreeModel *    model;
91    int               activeTorrentCount;
92
93    /* if the user doesn't want to be asked, don't ask */
94    if( !pref_flag_get( PREF_KEY_ASKQUIT ) )
95    {
96        func( cbdata );
97        return;
98    }
99
100    /* if there aren't any active torrents, don't ask */
101    model = tr_core_model( core );
102    activeTorrentCount = 0;
103    gtk_tree_model_foreach( model, countActiveTorrents, &activeTorrentCount );
104    if( !activeTorrentCount )
105    {
106        func( cbdata );
107        return;
108    }
109
110    stuff          = g_new( struct quitdata, 1 );
111    stuff->func    = func;
112    stuff->cbdata  = cbdata;
113    stuff->core    = core;
114
115    wind = gtk_message_dialog_new_with_markup(
116         parent,
117        GTK_DIALOG_DESTROY_WITH_PARENT,
118        GTK_MESSAGE_WARNING,
119        GTK_BUTTONS_NONE,
120        _(
121            "<big><b>Quit Transmission?</b></big>" ) );
122
123    gtk_dialog_add_button( GTK_DIALOG( wind ), GTK_STOCK_CANCEL,
124                                               GTK_RESPONSE_CANCEL );
125    w = gtk_dialog_add_button( GTK_DIALOG( wind ), GTK_STOCK_QUIT,
126                                                   GTK_RESPONSE_ACCEPT );
127    gtk_dialog_set_default_response( GTK_DIALOG( wind ),
128                                     GTK_RESPONSE_ACCEPT );
129    gtk_dialog_set_alternative_button_order( GTK_DIALOG( wind ),
130                                             GTK_RESPONSE_ACCEPT,
131                                             GTK_RESPONSE_CANCEL,
132                                             -1 );
133    dontask = gtk_check_button_new_with_mnemonic( _( "_Don't ask me again" ) );
134    stuff->dontask = dontask;
135
136    gtk_box_pack_start( GTK_BOX( GTK_DIALOG(
137                                     wind )->vbox ), dontask, FALSE, FALSE,
138                        GUI_PAD );
139
140    g_signal_connect( G_OBJECT( wind ), "response",
141                      G_CALLBACK( quitresp ), stuff );
142    gtk_widget_grab_focus( w );
143
144    gtk_widget_show_all( wind );
145}
146
147/***
148****
149***/
150
151struct DeleteData
152{
153    gboolean    delete_files;
154    GSList *    torrents;
155    TrCore *    core;
156};
157
158static void
159removeTorrents( struct DeleteData * data )
160{
161    GSList * l;
162
163    for( l = data->torrents; l != NULL; l = l->next )
164        tr_core_remove_torrent( data->core, l->data, data->delete_files );
165    g_slist_free( data->torrents );
166    data->torrents = NULL;
167}
168
169static void
170removeResponse( GtkDialog * dialog,
171                gint        response,
172                gpointer    gdata )
173{
174    struct DeleteData * data = gdata;
175
176    if( response == GTK_RESPONSE_ACCEPT )
177        removeTorrents( data );
178    else
179        g_slist_foreach( data->torrents, (GFunc)g_object_unref, NULL );
180
181    gtk_widget_destroy( GTK_WIDGET( dialog ) );
182    g_slist_free( data->torrents );
183    g_free( data );
184}
185
186struct count_data
187{
188    int incomplete;
189    int connected;
190};
191
192static void
193countBusyTorrents( gpointer gtor, gpointer gdata )
194{
195    const tr_stat * stat = tr_torrent_stat( gtor );
196    struct count_data * data = gdata;
197
198    if( stat->leftUntilDone ) ++data->incomplete;
199    if( stat->peersConnected ) ++data->connected;
200}
201
202void
203confirmRemove( GtkWindow * parent,
204               TrCore *    core,
205               GSList *    torrents,
206               gboolean    delete_files )
207{
208    GtkWidget *         d;
209    const int           count = g_slist_length( torrents );
210    struct count_data   counts;
211    const char        * primary_text;
212    GString           * secondary_text;
213    struct DeleteData * dd;
214
215    if( !count )
216        return;
217
218    dd = g_new0( struct DeleteData, 1 );
219    dd->core = core;
220    dd->torrents = torrents;
221    dd->delete_files = delete_files;
222
223    counts.incomplete = 0;
224    counts.connected = 0;
225    g_slist_foreach( torrents, countBusyTorrents, &counts );
226
227    if( !counts.incomplete && !counts.connected && !delete_files ) /* don't prompt boring torrents */
228    {
229        removeTorrents( dd );
230        g_free( dd );
231        return;
232    }
233
234    if( !delete_files )
235    {
236        primary_text = ngettext( "Remove torrent?",
237                                 "Remove torrents?",
238                                 count );
239    }
240    else
241    {
242        primary_text = ngettext( "Delete this torrent's downloaded files?",
243                                 "Delete these torrents' downloaded files?",
244                                 count );
245    }
246
247    secondary_text = g_string_new( NULL );
248
249    if( !counts.incomplete && !counts.connected )
250    {
251        /* boring -- no secondary text needed */
252    }
253    else if( count == counts.incomplete )
254    {
255        g_string_assign( secondary_text, ngettext( "This torrent has not finished downloading.",
256                                                   "These torrents have not finished downloading.",
257                                                   count ) );
258    }
259    else if( count == counts.connected )
260    {
261        g_string_assign( secondary_text, ngettext( "This torrent is connected to peers.",
262                                                   "These torrents are connected to peers.",
263                                                   count ) );
264    }
265    else
266    {
267        if( counts.connected )
268            g_string_append( secondary_text, ngettext( "One of these torrents is connected to peers.",
269                                                       "Some of these torrents are connected to peers.",
270                                                       counts.connected ) );
271        if( counts.connected && counts.incomplete )
272            g_string_append( secondary_text, "\n" );
273
274        if( counts.incomplete )
275            g_string_assign( secondary_text, ngettext( "One of these torrents has not finished downloading.",
276                                                       "Some of these torrents have not finished downloading.",
277                                                       counts.incomplete ) );
278    }
279
280    d = gtk_message_dialog_new_with_markup( parent,
281                                            GTK_DIALOG_DESTROY_WITH_PARENT,
282                                            GTK_MESSAGE_WARNING,
283                                            GTK_BUTTONS_NONE,
284                                            "<big><b>%s</b></big>",
285                                            primary_text );
286    if( secondary_text->len )
287        gtk_message_dialog_format_secondary_markup( GTK_MESSAGE_DIALOG( d ),
288                                                    "%s", secondary_text->str );
289    gtk_dialog_add_buttons( GTK_DIALOG( d ),
290                            GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
291                            ( delete_files ? GTK_STOCK_DELETE :
292                              GTK_STOCK_REMOVE ), GTK_RESPONSE_ACCEPT,
293                            NULL );
294    gtk_dialog_set_default_response( GTK_DIALOG ( d ),
295                                     GTK_RESPONSE_CANCEL );
296    gtk_dialog_set_alternative_button_order( GTK_DIALOG( d ),
297                                             GTK_RESPONSE_ACCEPT,
298                                             GTK_RESPONSE_CANCEL,
299                                             -1 );
300    g_signal_connect( d, "response", G_CALLBACK( removeResponse ), dd );
301    gtk_widget_show_all( d );
302
303    g_string_free( secondary_text, TRUE );
304}
Note: See TracBrowser for help on using the repository browser.