~ucl-cs-study-devs/activityfinder/thunar-vivid-ptsd

« back to all changes in this revision

Viewing changes to thunar/thunar-progress-dialog.c

  • Committer: Steve Dodier-Lazaro
  • Date: 2015-09-03 02:01:48 UTC
  • Revision ID: sidnioulz@gmail.com-20150903020148-i44kbe7u0nfwq2hl
Adding the UCL events

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* vi:set et ai sw=2 sts=2 ts=2: */
 
2
/*-
 
3
 * Copyright (c) 2009-2010 Jannis Pohlmann <jannis@xfce.org>
 
4
 *
 
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.
 
9
 *
 
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.
 
14
 *
 
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.
 
19
 */
 
20
 
 
21
#ifdef HAVE_CONFIG_H
 
22
#include <config.h>
 
23
#endif
 
24
 
 
25
#include <gtk/gtk.h>
 
26
 
 
27
#include <thunar/thunar-private.h>
 
28
#include <thunar/thunar-progress-dialog.h>
 
29
#include <thunar/thunar-progress-view.h>
 
30
 
 
31
 
 
32
 
 
33
#define SCROLLVIEW_THRESHOLD 5
 
34
 
 
35
 
 
36
 
 
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);
 
45
 
 
46
 
 
47
 
 
48
struct _ThunarProgressDialogClass
 
49
{
 
50
  GtkWindowClass __parent__;
 
51
};
 
52
 
 
53
struct _ThunarProgressDialog
 
54
{
 
55
  GtkWindow      __parent__;
 
56
 
 
57
  GtkStatusIcon *status_icon;
 
58
  GtkWidget     *scrollwin;
 
59
  GtkWidget     *vbox;
 
60
  GtkWidget     *content_box;
 
61
 
 
62
  GList         *views;
 
63
 
 
64
  gint           x;
 
65
  gint           y;
 
66
};
 
67
 
 
68
 
 
69
 
 
70
G_DEFINE_TYPE (ThunarProgressDialog, thunar_progress_dialog, GTK_TYPE_WINDOW);
 
71
 
 
72
 
 
73
 
 
74
static void
 
75
thunar_progress_dialog_class_init (ThunarProgressDialogClass *klass)
 
76
{
 
77
  GObjectClass *gobject_class;
 
78
 
 
79
  /* Determine parent type class */
 
80
  thunar_progress_dialog_parent_class = g_type_class_peek_parent (klass);
 
81
 
 
82
  gobject_class = G_OBJECT_CLASS (klass);
 
83
  gobject_class->dispose = thunar_progress_dialog_dispose;
 
84
  gobject_class->finalize = thunar_progress_dialog_finalize;
 
85
}
 
86
 
 
87
 
 
88
 
 
89
static void
 
90
thunar_progress_dialog_init (ThunarProgressDialog *dialog)
 
91
{
 
92
  dialog->views = NULL;
 
93
 
 
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);
 
100
 
 
101
  g_signal_connect_swapped (dialog, "show", 
 
102
                            G_CALLBACK (thunar_progress_dialog_shown), dialog);
 
103
 
 
104
  g_signal_connect (dialog, "delete-event", 
 
105
                    G_CALLBACK (thunar_progress_dialog_closed), dialog);
 
106
 
 
107
  dialog->vbox = gtk_vbox_new (FALSE, 0);
 
108
  gtk_container_add (GTK_CONTAINER (dialog), dialog->vbox);
 
109
  gtk_widget_show (dialog->vbox);
 
110
 
 
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);
 
115
}
 
116
 
 
117
 
 
118
 
 
119
static void
 
120
thunar_progress_dialog_dispose (GObject *object)
 
121
{
 
122
  (*G_OBJECT_CLASS (thunar_progress_dialog_parent_class)->dispose) (object);
 
123
}
 
124
 
 
125
 
 
126
 
 
127
static void
 
128
thunar_progress_dialog_finalize (GObject *object)
 
129
{
 
130
  ThunarProgressDialog *dialog = THUNAR_PROGRESS_DIALOG (object);
 
131
 
 
132
  /* destroy the status icon */
 
133
  if (dialog->status_icon != NULL)
 
134
    {
 
135
      gtk_status_icon_set_visible (dialog->status_icon, FALSE);
 
136
      g_object_unref (dialog->status_icon);
 
137
    }
 
138
 
 
139
  /* free the view list */
 
140
  g_list_free (dialog->views);
 
141
 
 
142
  (*G_OBJECT_CLASS (thunar_progress_dialog_parent_class)->finalize) (object);
 
143
}
 
144
 
 
145
 
 
146
 
 
147
static void
 
148
thunar_progress_dialog_shown (ThunarProgressDialog *dialog)
 
149
{
 
150
  _thunar_return_if_fail (THUNAR_IS_PROGRESS_DIALOG (dialog));
 
151
 
 
152
  /* show the status icon */
 
153
  if (dialog->status_icon == NULL)
 
154
    {
 
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));
 
160
    }
 
161
}
 
162
 
 
163
 
 
164
 
 
165
static gboolean
 
166
thunar_progress_dialog_closed (ThunarProgressDialog *dialog)
 
167
{
 
168
  _thunar_return_val_if_fail (THUNAR_IS_PROGRESS_DIALOG (dialog), FALSE);
 
169
 
 
170
  /* remember the position of the dialog */
 
171
  gtk_window_get_position (GTK_WINDOW (dialog), &dialog->x, &dialog->y);
 
172
 
 
173
  /* hide the progress dialog */
 
174
  gtk_widget_hide (GTK_WIDGET (dialog));
 
175
 
 
176
  /* don't destroy the dialog */
 
177
  return TRUE;
 
178
}
 
179
 
 
180
 
 
181
 
 
182
static gboolean
 
183
thunar_progress_dialog_toggled (ThunarProgressDialog *dialog,
 
184
                                GdkEventButton       *event,
 
185
                                GtkStatusIcon        *status_icon)
 
186
{
 
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);
 
189
 
 
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)))
 
193
    {
 
194
      /* remember the position of the dialog */
 
195
      gtk_window_get_position (GTK_WINDOW (dialog), &dialog->x, &dialog->y);
 
196
 
 
197
      /* it is, so hide it now */
 
198
      gtk_widget_hide (GTK_WIDGET (dialog));
 
199
    }
 
200
  else
 
201
    {
 
202
      /* check if the dialog is invisible */
 
203
      if (!gtk_widget_get_visible (GTK_WIDGET (dialog)))
 
204
        {
 
205
          /* restore its previous position before presenting it */
 
206
          gtk_window_move (GTK_WINDOW (dialog), dialog->x, dialog->y);
 
207
        }
 
208
 
 
209
      /* it's not, so we need to raise it above other windows */
 
210
      gtk_window_present_with_time (GTK_WINDOW (dialog), event->time);
 
211
    }
 
212
 
 
213
  return TRUE;
 
214
}
 
215
 
 
216
 
 
217
 
 
218
static void
 
219
thunar_progress_dialog_view_needs_attention (ThunarProgressDialog *dialog,
 
220
                                             ThunarProgressView   *view)
 
221
{
 
222
  _thunar_return_if_fail (THUNAR_IS_PROGRESS_DIALOG (dialog));
 
223
  _thunar_return_if_fail (THUNAR_IS_PROGRESS_VIEW (view));
 
224
 
 
225
  /* TODO scroll to the view */
 
226
 
 
227
  /* raise the dialog */
 
228
  gtk_window_present (GTK_WINDOW (dialog));
 
229
}
 
230
 
 
231
 
 
232
 
 
233
static void
 
234
thunar_progress_dialog_job_finished (ThunarProgressDialog *dialog,
 
235
                                     ThunarProgressView   *view)
 
236
{
 
237
  guint n_views;
 
238
 
 
239
  _thunar_return_if_fail (THUNAR_IS_PROGRESS_DIALOG (dialog));
 
240
  _thunar_return_if_fail (THUNAR_IS_PROGRESS_VIEW (view));
 
241
 
 
242
  /* remove the view from the list */
 
243
  dialog->views = g_list_remove (dialog->views, view);
 
244
 
 
245
  /* destroy the widget */
 
246
  gtk_widget_destroy (GTK_WIDGET (view));
 
247
 
 
248
  /* determine the number of views left */
 
249
  n_views = g_list_length (dialog->views);
 
250
 
 
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)
 
254
    {
 
255
      /* reparent the content box */
 
256
      gtk_widget_reparent (dialog->content_box, dialog->vbox);
 
257
 
 
258
      /* destroy the scroll win */
 
259
      gtk_widget_destroy (dialog->scrollwin);
 
260
    }
 
261
 
 
262
  /* check if we have less than SCROLLVIEW_THRESHOLD views 
 
263
   * and need to shrink the window */
 
264
  if (n_views < SCROLLVIEW_THRESHOLD)
 
265
    {
 
266
      /* try to shrink the window */
 
267
      gtk_window_resize (GTK_WINDOW (dialog), 450, 10);
 
268
    }
 
269
 
 
270
  /* check if we still have at least one view */
 
271
  if (dialog->views != NULL)
 
272
    {
 
273
      /* update the status icon */
 
274
      if (dialog->status_icon != NULL)
 
275
        thunar_progress_dialog_update_status_icon (dialog);
 
276
    }
 
277
  else
 
278
    {
 
279
      /* destroy the dialog as there are no views left */
 
280
      gtk_widget_destroy (GTK_WIDGET (dialog));
 
281
    }
 
282
}
 
283
 
 
284
 
 
285
 
 
286
static void
 
287
thunar_progress_dialog_update_status_icon (ThunarProgressDialog *dialog)
 
288
{
 
289
  gchar *tooltip_text;
 
290
  guint  n_views;
 
291
 
 
292
  _thunar_return_if_fail (THUNAR_IS_PROGRESS_DIALOG (dialog));
 
293
  _thunar_return_if_fail (GTK_IS_STATUS_ICON (dialog->status_icon));
 
294
 
 
295
  /* determine the number of views now being active */
 
296
  n_views = g_list_length (dialog->views);
 
297
 
 
298
  /* build the tooltip text */
 
299
  tooltip_text = g_strdup_printf (ngettext ("%d file operation running", 
 
300
                                            "%d file operations running",
 
301
                                            n_views), 
 
302
                                            n_views);
 
303
 
 
304
  /* update the tooltip */
 
305
  gtk_status_icon_set_tooltip_text (dialog->status_icon, tooltip_text);
 
306
 
 
307
  /* free the string */
 
308
  g_free (tooltip_text);
 
309
}
 
310
 
 
311
 
 
312
 
 
313
 
 
314
 
 
315
 
 
316
GtkWidget*
 
317
thunar_progress_dialog_new (void)
 
318
{
 
319
  return g_object_new (THUNAR_TYPE_PROGRESS_DIALOG, NULL);
 
320
}
 
321
 
 
322
 
 
323
 
 
324
void
 
325
thunar_progress_dialog_add_job (ThunarProgressDialog *dialog,
 
326
                                ThunarJob            *job,
 
327
                                const gchar          *icon_name,
 
328
                                const gchar          *title)
 
329
{
 
330
  GtkWidget *viewport;
 
331
  GtkWidget *view;
 
332
 
 
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));
 
336
 
 
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);
 
342
 
 
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);
 
346
 
 
347
  /* add the view to the list of known views */
 
348
  dialog->views = g_list_prepend (dialog->views, view);
 
349
 
 
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)
 
353
    {
 
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);
 
360
 
 
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);
 
367
 
 
368
      /* move the content box into the viewport */
 
369
      gtk_widget_reparent (dialog->content_box, viewport);
 
370
    }
 
371
 
 
372
  g_signal_connect_swapped (view, "need-attention", 
 
373
                            G_CALLBACK (thunar_progress_dialog_view_needs_attention), dialog);
 
374
 
 
375
  g_signal_connect_swapped (view, "finished",
 
376
                            G_CALLBACK (thunar_progress_dialog_job_finished), dialog);
 
377
 
 
378
  if (dialog->status_icon != NULL)
 
379
    thunar_progress_dialog_update_status_icon (dialog);
 
380
}
 
381
 
 
382
 
 
383
 
 
384
gboolean
 
385
thunar_progress_dialog_has_jobs (ThunarProgressDialog *dialog)
 
386
{
 
387
  _thunar_return_val_if_fail (THUNAR_IS_PROGRESS_DIALOG (dialog), FALSE);
 
388
  return dialog->views != NULL;
 
389
}