1
/* vi:set et ai sw=2 sts=2 ts=2: */
3
* Copyright (c) 2009-2010 Jannis Pohlmann <jannis@xfce.org>
5
* This program is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU General Public License as
7
* published by the Free Software Foundation; either version 2 of
8
* the License, or (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public
16
* License along with this program; if not, write to the Free
17
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18
* Boston, MA 02110-1301, USA.
27
#include <thunar/thunar-private.h>
28
#include <thunar/thunar-progress-dialog.h>
29
#include <thunar/thunar-progress-view.h>
33
#define SCROLLVIEW_THRESHOLD 5
37
static void thunar_progress_dialog_dispose (GObject *object);
38
static void thunar_progress_dialog_finalize (GObject *object);
39
static void thunar_progress_dialog_shown (ThunarProgressDialog *dialog);
40
static gboolean thunar_progress_dialog_closed (ThunarProgressDialog *dialog);
41
static gboolean thunar_progress_dialog_toggled (ThunarProgressDialog *dialog,
42
GdkEventButton *button,
43
GtkStatusIcon *status_icon);
44
static void thunar_progress_dialog_update_status_icon (ThunarProgressDialog *dialog);
48
struct _ThunarProgressDialogClass
50
GtkWindowClass __parent__;
53
struct _ThunarProgressDialog
57
GtkStatusIcon *status_icon;
60
GtkWidget *content_box;
70
G_DEFINE_TYPE (ThunarProgressDialog, thunar_progress_dialog, GTK_TYPE_WINDOW);
75
thunar_progress_dialog_class_init (ThunarProgressDialogClass *klass)
77
GObjectClass *gobject_class;
79
/* Determine parent type class */
80
thunar_progress_dialog_parent_class = g_type_class_peek_parent (klass);
82
gobject_class = G_OBJECT_CLASS (klass);
83
gobject_class->dispose = thunar_progress_dialog_dispose;
84
gobject_class->finalize = thunar_progress_dialog_finalize;
90
thunar_progress_dialog_init (ThunarProgressDialog *dialog)
94
gtk_window_set_title (GTK_WINDOW (dialog), _("File Operation Progress"));
95
gtk_window_set_default_size (GTK_WINDOW (dialog), 450, 10);
96
gtk_window_set_modal (GTK_WINDOW (dialog), FALSE);
97
gtk_window_set_transient_for (GTK_WINDOW (dialog), NULL);
98
gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), FALSE);
99
gtk_window_set_type_hint (GTK_WINDOW (dialog), GDK_WINDOW_TYPE_HINT_DIALOG);
101
g_signal_connect_swapped (dialog, "show",
102
G_CALLBACK (thunar_progress_dialog_shown), dialog);
104
g_signal_connect (dialog, "delete-event",
105
G_CALLBACK (thunar_progress_dialog_closed), dialog);
107
dialog->vbox = gtk_vbox_new (FALSE, 0);
108
gtk_container_add (GTK_CONTAINER (dialog), dialog->vbox);
109
gtk_widget_show (dialog->vbox);
111
dialog->content_box = gtk_vbox_new (FALSE, 12);
112
gtk_container_set_border_width (GTK_CONTAINER (dialog->content_box), 8);
113
gtk_container_add (GTK_CONTAINER (dialog->vbox), dialog->content_box);
114
gtk_widget_show (dialog->content_box);
120
thunar_progress_dialog_dispose (GObject *object)
122
(*G_OBJECT_CLASS (thunar_progress_dialog_parent_class)->dispose) (object);
128
thunar_progress_dialog_finalize (GObject *object)
130
ThunarProgressDialog *dialog = THUNAR_PROGRESS_DIALOG (object);
132
/* destroy the status icon */
133
if (dialog->status_icon != NULL)
135
gtk_status_icon_set_visible (dialog->status_icon, FALSE);
136
g_object_unref (dialog->status_icon);
139
/* free the view list */
140
g_list_free (dialog->views);
142
(*G_OBJECT_CLASS (thunar_progress_dialog_parent_class)->finalize) (object);
148
thunar_progress_dialog_shown (ThunarProgressDialog *dialog)
150
_thunar_return_if_fail (THUNAR_IS_PROGRESS_DIALOG (dialog));
152
/* show the status icon */
153
if (dialog->status_icon == NULL)
155
dialog->status_icon = gtk_status_icon_new_from_icon_name ("stock_folder-copy");
156
thunar_progress_dialog_update_status_icon (dialog);
157
g_signal_connect_swapped (dialog->status_icon, "button-press-event",
158
G_CALLBACK (thunar_progress_dialog_toggled),
159
GTK_WIDGET (dialog));
166
thunar_progress_dialog_closed (ThunarProgressDialog *dialog)
168
_thunar_return_val_if_fail (THUNAR_IS_PROGRESS_DIALOG (dialog), FALSE);
170
/* remember the position of the dialog */
171
gtk_window_get_position (GTK_WINDOW (dialog), &dialog->x, &dialog->y);
173
/* hide the progress dialog */
174
gtk_widget_hide (GTK_WIDGET (dialog));
176
/* don't destroy the dialog */
183
thunar_progress_dialog_toggled (ThunarProgressDialog *dialog,
184
GdkEventButton *event,
185
GtkStatusIcon *status_icon)
187
_thunar_return_val_if_fail (THUNAR_IS_PROGRESS_DIALOG (dialog), FALSE);
188
_thunar_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), FALSE);
190
/* check if the window is visible and has the focus */
191
if (gtk_widget_get_visible (GTK_WIDGET (dialog))
192
&& gtk_window_is_active (GTK_WINDOW (dialog)))
194
/* remember the position of the dialog */
195
gtk_window_get_position (GTK_WINDOW (dialog), &dialog->x, &dialog->y);
197
/* it is, so hide it now */
198
gtk_widget_hide (GTK_WIDGET (dialog));
202
/* check if the dialog is invisible */
203
if (!gtk_widget_get_visible (GTK_WIDGET (dialog)))
205
/* restore its previous position before presenting it */
206
gtk_window_move (GTK_WINDOW (dialog), dialog->x, dialog->y);
209
/* it's not, so we need to raise it above other windows */
210
gtk_window_present_with_time (GTK_WINDOW (dialog), event->time);
219
thunar_progress_dialog_view_needs_attention (ThunarProgressDialog *dialog,
220
ThunarProgressView *view)
222
_thunar_return_if_fail (THUNAR_IS_PROGRESS_DIALOG (dialog));
223
_thunar_return_if_fail (THUNAR_IS_PROGRESS_VIEW (view));
225
/* TODO scroll to the view */
227
/* raise the dialog */
228
gtk_window_present (GTK_WINDOW (dialog));
234
thunar_progress_dialog_job_finished (ThunarProgressDialog *dialog,
235
ThunarProgressView *view)
239
_thunar_return_if_fail (THUNAR_IS_PROGRESS_DIALOG (dialog));
240
_thunar_return_if_fail (THUNAR_IS_PROGRESS_VIEW (view));
242
/* remove the view from the list */
243
dialog->views = g_list_remove (dialog->views, view);
245
/* destroy the widget */
246
gtk_widget_destroy (GTK_WIDGET (view));
248
/* determine the number of views left */
249
n_views = g_list_length (dialog->views);
251
/* check if we've just removed the 4th view and are now left with
252
* SCROLLVIEW_THRESHOLD-1 of them, in which case we drop the scroll window */
253
if (n_views == SCROLLVIEW_THRESHOLD-1)
255
/* reparent the content box */
256
gtk_widget_reparent (dialog->content_box, dialog->vbox);
258
/* destroy the scroll win */
259
gtk_widget_destroy (dialog->scrollwin);
262
/* check if we have less than SCROLLVIEW_THRESHOLD views
263
* and need to shrink the window */
264
if (n_views < SCROLLVIEW_THRESHOLD)
266
/* try to shrink the window */
267
gtk_window_resize (GTK_WINDOW (dialog), 450, 10);
270
/* check if we still have at least one view */
271
if (dialog->views != NULL)
273
/* update the status icon */
274
if (dialog->status_icon != NULL)
275
thunar_progress_dialog_update_status_icon (dialog);
279
/* destroy the dialog as there are no views left */
280
gtk_widget_destroy (GTK_WIDGET (dialog));
287
thunar_progress_dialog_update_status_icon (ThunarProgressDialog *dialog)
292
_thunar_return_if_fail (THUNAR_IS_PROGRESS_DIALOG (dialog));
293
_thunar_return_if_fail (GTK_IS_STATUS_ICON (dialog->status_icon));
295
/* determine the number of views now being active */
296
n_views = g_list_length (dialog->views);
298
/* build the tooltip text */
299
tooltip_text = g_strdup_printf (ngettext ("%d file operation running",
300
"%d file operations running",
304
/* update the tooltip */
305
gtk_status_icon_set_tooltip_text (dialog->status_icon, tooltip_text);
307
/* free the string */
308
g_free (tooltip_text);
317
thunar_progress_dialog_new (void)
319
return g_object_new (THUNAR_TYPE_PROGRESS_DIALOG, NULL);
325
thunar_progress_dialog_add_job (ThunarProgressDialog *dialog,
327
const gchar *icon_name,
333
_thunar_return_if_fail (THUNAR_IS_PROGRESS_DIALOG (dialog));
334
_thunar_return_if_fail (THUNAR_IS_JOB (job));
335
_thunar_return_if_fail (g_utf8_validate (title, -1, NULL));
337
view = thunar_progress_view_new_with_job (job);
338
thunar_progress_view_set_icon_name (THUNAR_PROGRESS_VIEW (view), icon_name);
339
thunar_progress_view_set_title (THUNAR_PROGRESS_VIEW (view), title);
340
gtk_box_pack_start (GTK_BOX (dialog->content_box), view, FALSE, TRUE, 0);
341
gtk_widget_show (view);
343
/* use the first job's icon-name for the dialog */
344
if (dialog->views == NULL)
345
gtk_window_set_icon_name (GTK_WINDOW (dialog), icon_name);
347
/* add the view to the list of known views */
348
dialog->views = g_list_prepend (dialog->views, view);
350
/* check if we need to wrap the views in a scroll window (starting
351
* at SCROLLVIEW_THRESHOLD parallel operations */
352
if (g_list_length (dialog->views) == SCROLLVIEW_THRESHOLD)
354
/* create a scrolled window and add it to the dialog */
355
dialog->scrollwin = gtk_scrolled_window_new (NULL, NULL);
356
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (dialog->scrollwin),
357
GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
358
gtk_container_add (GTK_CONTAINER (dialog->vbox), dialog->scrollwin);
359
gtk_widget_show (dialog->scrollwin);
361
/* create a viewport for the content box */
362
viewport = gtk_viewport_new (gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (dialog->scrollwin)),
363
gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (dialog->scrollwin)));
364
gtk_viewport_set_shadow_type (GTK_VIEWPORT (viewport), GTK_SHADOW_NONE);
365
gtk_container_add (GTK_CONTAINER (dialog->scrollwin), viewport);
366
gtk_widget_show (viewport);
368
/* move the content box into the viewport */
369
gtk_widget_reparent (dialog->content_box, viewport);
372
g_signal_connect_swapped (view, "need-attention",
373
G_CALLBACK (thunar_progress_dialog_view_needs_attention), dialog);
375
g_signal_connect_swapped (view, "finished",
376
G_CALLBACK (thunar_progress_dialog_job_finished), dialog);
378
if (dialog->status_icon != NULL)
379
thunar_progress_dialog_update_status_icon (dialog);
385
thunar_progress_dialog_has_jobs (ThunarProgressDialog *dialog)
387
_thunar_return_val_if_fail (THUNAR_IS_PROGRESS_DIALOG (dialog), FALSE);
388
return dialog->views != NULL;