source: trunk/gtk/dialogs.c @ 5596

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

(gtk) #869: Minor HIG fixes for Exit/Remove/Delete? alerts

  • Property svn:keywords set to Date Rev Author Id
File size: 7.9 KB
Line 
1/******************************************************************************
2 * $Id: dialogs.c 5596 2008-04-12 15:01:43Z 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}
156
157
158static void
159removeResponse( GtkDialog * dialog, gint response, gpointer gdata )
160{
161    struct DeleteData * data = gdata;
162
163    if( response == GTK_RESPONSE_ACCEPT )
164        removeTorrents( data );
165    else
166        g_slist_foreach( data->torrents, (GFunc)g_object_unref, NULL );
167
168    gtk_widget_destroy( GTK_WIDGET( dialog ) );
169    g_free( data );
170}
171
172static void
173countBusyTorrents( gpointer gtor, gpointer busyCount )
174{
175    const tr_stat * stat = tr_torrent_stat( gtor );
176
177    if( stat->leftUntilDone || stat->peersConnected )
178        ++(*(int*)busyCount);
179}
180
181void
182confirmRemove( GtkWindow * parent,
183               TrCore    * core,
184               GSList    * torrents,
185               gboolean    delete_files )
186{
187    GtkWidget * d;
188    struct DeleteData * dd;
189    int busyCount;
190    const int count = g_slist_length( torrents );
191    const char * primary_text;
192    const char * secondary_text;
193
194    if( !count )
195        return;
196
197    dd = g_new0( struct DeleteData, 1 );
198    dd->core = core;
199    dd->torrents = torrents;
200    dd->delete_files = delete_files;
201
202    busyCount = 0;
203    g_slist_foreach( torrents, countBusyTorrents, &busyCount );
204
205    if( !busyCount && !delete_files ) /* don't prompt boring torrents */
206    {
207        removeTorrents( dd );
208        g_free( dd );
209        return;
210    }
211
212    if( !delete_files )
213        primary_text = ngettext( "Remove torrent?", "Remove torrents?", count );
214    else
215        primary_text = ngettext( "Delete this torrent's downloaded files?",
216                                 "Delete these torrents' downloaded files?",
217                                 count );
218
219    if( busyCount > 1 )
220        secondary_text = _( "Some of these torrents are incomplete or connected to peers." );
221    else if( busyCount == 0 )
222        secondary_text = NULL;
223    else
224        secondary_text = ngettext( "This torrent is incomplete or connected to peers.",
225                                   "One of these torrents is incomplete or connected to peers.",
226                                   count );
227
228    d = gtk_message_dialog_new_with_markup( parent,
229                                            GTK_DIALOG_DESTROY_WITH_PARENT,
230                                            GTK_MESSAGE_WARNING,
231                                            GTK_BUTTONS_NONE,
232                                            "<big><b>%s</b></big>", primary_text );
233    if( secondary_text )
234        gtk_message_dialog_format_secondary_markup( GTK_MESSAGE_DIALOG( d ), secondary_text );
235    gtk_dialog_add_buttons( GTK_DIALOG( d ),
236                            GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
237                            (delete_files ? GTK_STOCK_DELETE : GTK_STOCK_REMOVE), GTK_RESPONSE_ACCEPT,
238                            NULL );
239    gtk_dialog_set_default_response( GTK_DIALOG ( d ),
240                                     GTK_RESPONSE_CANCEL );
241    gtk_dialog_set_alternative_button_order( GTK_DIALOG( d ),
242                                             GTK_RESPONSE_ACCEPT,
243                                             GTK_RESPONSE_CANCEL,
244                                             -1 );
245    g_signal_connect( d, "response", G_CALLBACK( removeResponse ), dd );
246    gtk_widget_show_all( d );
247}
Note: See TracBrowser for help on using the repository browser.