source: trunk/gtk/dialogs.c @ 10536

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

(trunk) #3174 "Use IEC standard units (KiB, MiB, GiB) instead of (KB, MB, GB)" -- implemented for gtk, qt, daemon, cli, and web client

  • Property svn:keywords set to Date Rev Author Id
File size: 9.8 KB
Line 
1/******************************************************************************
2 * $Id: dialogs.c 10536 2010-04-28 01:26:46Z 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
179    gtk_widget_destroy( GTK_WIDGET( dialog ) );
180    g_slist_free( data->torrents );
181    g_free( data );
182}
183
184struct count_data
185{
186    int incomplete;
187    int connected;
188};
189
190static void
191countBusyTorrents( gpointer gtor, gpointer gdata )
192{
193    const tr_stat * stat = tr_torrent_stat( gtor );
194    struct count_data * data = gdata;
195
196    if( stat->leftUntilDone ) ++data->incomplete;
197    if( stat->peersConnected ) ++data->connected;
198}
199
200void
201confirmRemove( GtkWindow * parent,
202               TrCore *    core,
203               GSList *    torrents,
204               gboolean    delete_files )
205{
206    GtkWidget *         d;
207    const int           count = g_slist_length( torrents );
208    struct count_data   counts;
209    const char        * primary_text;
210    GString           * secondary_text;
211    struct DeleteData * dd;
212
213    if( !count )
214        return;
215
216    dd = g_new0( struct DeleteData, 1 );
217    dd->core = core;
218    dd->torrents = torrents;
219    dd->delete_files = delete_files;
220
221    counts.incomplete = 0;
222    counts.connected = 0;
223    g_slist_foreach( torrents, countBusyTorrents, &counts );
224
225    if( !counts.incomplete && !counts.connected && !delete_files ) /* don't prompt boring torrents */
226    {
227        removeTorrents( dd );
228        g_free( dd );
229        return;
230    }
231
232    if( !delete_files )
233    {
234        primary_text = ngettext( "Remove torrent?",
235                                 "Remove torrents?",
236                                 count );
237    }
238    else
239    {
240        primary_text = ngettext( "Delete this torrent's downloaded files?",
241                                 "Delete these torrents' downloaded files?",
242                                 count );
243    }
244
245    secondary_text = g_string_new( NULL );
246
247    if( !counts.incomplete && !counts.connected )
248    {
249        /* boring -- no secondary text needed */
250    }
251    else if( count == counts.incomplete )
252    {
253        g_string_assign( secondary_text, ngettext( "This torrent has not finished downloading.",
254                                                   "These torrents have not finished downloading.",
255                                                   count ) );
256    }
257    else if( count == counts.connected )
258    {
259        g_string_assign( secondary_text, ngettext( "This torrent is connected to peers.",
260                                                   "These torrents are connected to peers.",
261                                                   count ) );
262    }
263    else
264    {
265        if( counts.connected )
266            g_string_append( secondary_text, ngettext( "One of these torrents is connected to peers.",
267                                                       "Some of these torrents are connected to peers.",
268                                                       counts.connected ) );
269        if( counts.connected && counts.incomplete )
270            g_string_append( secondary_text, "\n" );
271
272        if( counts.incomplete )
273            g_string_assign( secondary_text, ngettext( "One of these torrents has not finished downloading.",
274                                                       "Some of these torrents have not finished downloading.",
275                                                       counts.incomplete ) );
276    }
277
278    d = gtk_message_dialog_new_with_markup( parent,
279                                            GTK_DIALOG_DESTROY_WITH_PARENT,
280                                            GTK_MESSAGE_WARNING,
281                                            GTK_BUTTONS_NONE,
282                                            "<big><b>%s</b></big>",
283                                            primary_text );
284    if( secondary_text->len )
285        gtk_message_dialog_format_secondary_markup( GTK_MESSAGE_DIALOG( d ),
286                                                    "%s", secondary_text->str );
287    gtk_dialog_add_buttons( GTK_DIALOG( d ),
288                            GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
289                            ( delete_files ? GTK_STOCK_DELETE :
290                              GTK_STOCK_REMOVE ), GTK_RESPONSE_ACCEPT,
291                            NULL );
292    gtk_dialog_set_default_response( GTK_DIALOG ( d ),
293                                     GTK_RESPONSE_CANCEL );
294    gtk_dialog_set_alternative_button_order( GTK_DIALOG( d ),
295                                             GTK_RESPONSE_ACCEPT,
296                                             GTK_RESPONSE_CANCEL,
297                                             -1 );
298    g_signal_connect( d, "response", G_CALLBACK( removeResponse ), dd );
299    gtk_widget_show_all( d );
300
301    g_string_free( secondary_text, TRUE );
302}
Note: See TracBrowser for help on using the repository browser.