~walkerlee/totem/pre-interview

« back to all changes in this revision

Viewing changes to libgd/libgd/gd-main-icon-view.c

  • Committer: Package Import Robot
  • Author(s): Jeremy Bicha
  • Date: 2013-05-26 00:07:51 UTC
  • mfrom: (1.6.1) (24.1.4 experimental)
  • Revision ID: package-import@ubuntu.com-20130526000751-kv8ap3x1di4qq8j2
Tags: 3.8.2-0ubuntu1
* Sync with Debian. Remaining changes: 
* debian/control.in:
  - Drop build-depends on libepc-ui-dev and libgrilo-0.2-dev (in universe)
  - Drop libxtst-dev build-depends so that the (redundant) fake key presses
    for inhibiting the screensaver are disabled (LP: #1007438)
  - Build-depend on libzeitgeist-dev
  - Suggest rather than recommend gstreamer components in universe
  - Add totem-plugins-extra
  - Add XB-Npp-Description and XB-Npp-Filename header to the 
    totem-mozilla package to improve ubufox/ubuntu plugin db integration 
  - Refer to Firefox in totem-mozilla description instead of Iceweasel
  - Don't have totem-mozilla recommend any particular browser
  - Drop obsolete python library dependencies since iplayer is no longer
    included
* debian/totem-common.install, debian/source_totem.py:
  - Install Ubuntu apport debugging hook
* debian/totem-plugins-extra.install:
  - Universe plugins split out of totem-plugins (currently only gromit)
* debian/totem-plugins.install:    
  - Skip the plugins split to -extra and add the zeitgeist plugin
* debian/rules:
  - Build with --fail-missing, to ensure we install everything. 
    + Ignore libtotem.{,l}a since we delibrately don't install these.
  - Re-enable hardening, make sure both PIE and BINDNOW are used
    by setting hardening=+all. (LP: #1039604)
* debian/patches/91_quicklist_entries.patch:
  - Add static quicklist
* debian/patches/92_gst-plugins-good.patch:
  - Build without unnecessary gstreamer1.0-bad dependency
* debian/patches/93_grilo_optional.patch:
  - Allow building without grilo while grilo MIR is still pending
* debian/patches/correct_desktop_mimetypes.patch:
  - Don't list the mimetypes after the unity lists
* debian/patches/revert_shell_menu.patch: 
  - revert the use of a shell menu until indicator-appmenu can handle
    the mixed shell/traditional menus itself
* New upstream release

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2011 Red Hat, Inc.
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or modify
 
5
 * it under the terms of the GNU Lesser General Public License as published by 
 
6
 * the Free Software Foundation; either version 2 of the License, or (at your
 
7
 * option) any later version.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful, but
 
10
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 
11
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
 
12
 * License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU Lesser General Public License 
 
15
 * along with this program; if not, write to the Free Software Foundation,
 
16
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
17
 *
 
18
 * Author: Cosimo Cecchi <cosimoc@redhat.com>
 
19
 *
 
20
 */
 
21
 
 
22
#include "gd-main-icon-view.h"
 
23
#include "gd-main-view-generic.h"
 
24
#include "gd-toggle-pixbuf-renderer.h"
 
25
#include "gd-two-lines-renderer.h"
 
26
 
 
27
#include <math.h>
 
28
#include <glib/gi18n.h>
 
29
 
 
30
#define VIEW_ITEM_WIDTH 140
 
31
#define VIEW_ITEM_WRAP_WIDTH 128
 
32
#define VIEW_COLUMN_SPACING 20
 
33
#define VIEW_MARGIN 16
 
34
 
 
35
struct _GdMainIconViewPrivate {
 
36
  GtkCellRenderer *pixbuf_cell;
 
37
  gboolean selection_mode;
 
38
};
 
39
 
 
40
static void gd_main_view_generic_iface_init (GdMainViewGenericIface *iface);
 
41
G_DEFINE_TYPE_WITH_CODE (GdMainIconView, gd_main_icon_view, GTK_TYPE_ICON_VIEW,
 
42
                         G_IMPLEMENT_INTERFACE (GD_TYPE_MAIN_VIEW_GENERIC,
 
43
                                                gd_main_view_generic_iface_init))
 
44
 
 
45
static GtkTreePath*
 
46
get_source_row (GdkDragContext *context)
 
47
{
 
48
  GtkTreeRowReference *ref;
 
49
 
 
50
  ref = g_object_get_data (G_OBJECT (context), "gtk-icon-view-source-row");
 
51
 
 
52
  if (ref)
 
53
    return gtk_tree_row_reference_get_path (ref);
 
54
  else
 
55
    return NULL;
 
56
}
 
57
 
 
58
static void
 
59
gd_main_icon_view_drag_data_get (GtkWidget *widget,
 
60
                                 GdkDragContext *drag_context,
 
61
                                 GtkSelectionData *data,
 
62
                                 guint info,
 
63
                                 guint time)
 
64
{
 
65
  GdMainIconView *self = GD_MAIN_ICON_VIEW (widget);
 
66
  GtkTreeModel *model = gtk_icon_view_get_model (GTK_ICON_VIEW (self));
 
67
 
 
68
  if (info != 0)
 
69
    return;
 
70
 
 
71
  _gd_main_view_generic_dnd_common (model, self->priv->selection_mode,
 
72
                                    get_source_row (drag_context), data);
 
73
 
 
74
  GTK_WIDGET_CLASS (gd_main_icon_view_parent_class)->drag_data_get (widget, drag_context,
 
75
                                                                    data, info, time);
 
76
}
 
77
 
 
78
static void
 
79
gd_main_icon_view_constructed (GObject *obj)
 
80
{
 
81
  GdMainIconView *self = GD_MAIN_ICON_VIEW (obj);
 
82
  GtkCellRenderer *cell;
 
83
  const GtkTargetEntry targets[] = {
 
84
    { (char *) "text/uri-list", GTK_TARGET_OTHER_APP, 0 }
 
85
  };
 
86
 
 
87
  G_OBJECT_CLASS (gd_main_icon_view_parent_class)->constructed (obj);
 
88
 
 
89
  gtk_widget_set_hexpand (GTK_WIDGET (self), TRUE);
 
90
  gtk_widget_set_vexpand (GTK_WIDGET (self), TRUE);
 
91
  gtk_icon_view_set_selection_mode (GTK_ICON_VIEW (self), GTK_SELECTION_NONE);
 
92
 
 
93
  g_object_set (self,
 
94
                "column-spacing", VIEW_COLUMN_SPACING,
 
95
                "margin", VIEW_MARGIN,
 
96
                NULL);
 
97
 
 
98
  self->priv->pixbuf_cell = cell = gd_toggle_pixbuf_renderer_new ();
 
99
  g_object_set (cell,
 
100
                "xalign", 0.5,
 
101
                "yalign", 0.5,
 
102
                NULL);
 
103
 
 
104
  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (self), cell, FALSE);
 
105
  gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (self), cell,
 
106
                                 "active", GD_MAIN_COLUMN_SELECTED);
 
107
  gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (self), cell,
 
108
                                 "pixbuf", GD_MAIN_COLUMN_ICON);
 
109
 
 
110
  cell = gd_two_lines_renderer_new ();
 
111
  g_object_set (cell,
 
112
                "xalign", 0.5,
 
113
                "alignment", PANGO_ALIGN_CENTER,
 
114
                "wrap-mode", PANGO_WRAP_WORD_CHAR,
 
115
                "wrap-width", VIEW_ITEM_WRAP_WIDTH,
 
116
                "text-lines", 3,
 
117
                NULL);
 
118
  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (self), cell, FALSE);
 
119
  gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (self), cell,
 
120
                                 "text", GD_MAIN_COLUMN_PRIMARY_TEXT);
 
121
  gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (self), cell,
 
122
                                 "line-two", GD_MAIN_COLUMN_SECONDARY_TEXT);
 
123
 
 
124
  gtk_icon_view_enable_model_drag_source (GTK_ICON_VIEW (self),
 
125
                                          GDK_BUTTON1_MASK,
 
126
                                          targets, 1,
 
127
                                          GDK_ACTION_COPY);
 
128
}
 
129
 
 
130
static void
 
131
path_from_line_rects (cairo_t *cr,
 
132
                      GdkRectangle *lines,
 
133
                      int n_lines)
 
134
{
 
135
  int start_line, end_line;
 
136
  GdkRectangle *r;
 
137
  int i;
 
138
 
 
139
  /* Join rows vertically by extending to the middle */
 
140
  for (i = 0; i < n_lines - 1; i++)
 
141
    {
 
142
      GdkRectangle *r1 = &lines[i];
 
143
      GdkRectangle *r2 = &lines[i+1];
 
144
      int gap = r2->y - (r1->y + r1->height);
 
145
      int old_y;
 
146
 
 
147
      r1->height += gap / 2;
 
148
      old_y = r2->y;
 
149
      r2->y = r1->y + r1->height;
 
150
      r2->height += old_y - r2->y;
 
151
    }
 
152
 
 
153
  cairo_new_path (cr);
 
154
  start_line = 0;
 
155
 
 
156
  do
 
157
    {
 
158
      for (i = start_line; i < n_lines; i++)
 
159
        {
 
160
          r = &lines[i];
 
161
          if (i == start_line)
 
162
            cairo_move_to (cr, r->x + r->width, r->y);
 
163
          else
 
164
            cairo_line_to (cr, r->x + r->width, r->y);
 
165
          cairo_line_to (cr, r->x + r->width, r->y + r->height);
 
166
 
 
167
          if (i < n_lines - 1 &&
 
168
              (r->x + r->width < lines[i+1].x ||
 
169
               r->x > lines[i+1].x + lines[i+1].width))
 
170
            {
 
171
              i++;
 
172
              break;
 
173
            }
 
174
        }
 
175
      end_line = i;
 
176
      for (i = end_line - 1; i >= start_line; i--)
 
177
        {
 
178
          r = &lines[i];
 
179
          cairo_line_to (cr, r->x, r->y + r->height);
 
180
          cairo_line_to (cr, r->x, r->y);
 
181
        }
 
182
      cairo_close_path (cr);
 
183
      start_line = end_line;
 
184
    }
 
185
  while (end_line < n_lines);
 
186
}
 
187
 
 
188
static gboolean
 
189
gd_main_icon_view_draw (GtkWidget *widget,
 
190
                        cairo_t   *cr)
 
191
{
 
192
  GdMainIconView *self = GD_MAIN_ICON_VIEW (widget);
 
193
  GtkAllocation allocation;
 
194
  GtkStyleContext *context;
 
195
  GdkRectangle line_rect;
 
196
  GdkRectangle rect;
 
197
  GtkTreePath *path;
 
198
  GArray *lines;
 
199
  GtkTreePath *rubberband_start, *rubberband_end;
 
200
 
 
201
  GTK_WIDGET_CLASS (gd_main_icon_view_parent_class)->draw (widget, cr);
 
202
 
 
203
  _gd_main_view_generic_get_rubberband_range (GD_MAIN_VIEW_GENERIC (self),
 
204
                                              &rubberband_start, &rubberband_end);
 
205
 
 
206
  if (rubberband_start)
 
207
    {
 
208
      cairo_save (cr);
 
209
 
 
210
      context = gtk_widget_get_style_context (widget);
 
211
 
 
212
      gtk_style_context_save (context);
 
213
      gtk_style_context_add_class (context, GTK_STYLE_CLASS_RUBBERBAND);
 
214
 
 
215
      path = gtk_tree_path_copy (rubberband_start);
 
216
 
 
217
      line_rect.width = 0;
 
218
      lines = g_array_new (FALSE, FALSE, sizeof (GdkRectangle));
 
219
 
 
220
      while (gtk_tree_path_compare (path, rubberband_end) <= 0)
 
221
        {
 
222
          if (gtk_icon_view_get_cell_rect (GTK_ICON_VIEW (widget),
 
223
                                           path,
 
224
                                           NULL, &rect))
 
225
            {
 
226
              if (line_rect.width == 0)
 
227
                line_rect = rect;
 
228
              else
 
229
                {
 
230
                  if (rect.y == line_rect.y)
 
231
                    gdk_rectangle_union (&rect, &line_rect, &line_rect);
 
232
                  else
 
233
                    {
 
234
                      g_array_append_val (lines, line_rect);
 
235
                      line_rect = rect;
 
236
                    }
 
237
                }
 
238
            }
 
239
          gtk_tree_path_next (path);
 
240
        }
 
241
 
 
242
      if (line_rect.width != 0)
 
243
        g_array_append_val (lines, line_rect);
 
244
 
 
245
      if (lines->len > 0)
 
246
        {
 
247
          GtkStateFlags state;
 
248
          cairo_path_t *path;
 
249
          GtkBorder border;
 
250
          GdkRGBA border_color;
 
251
 
 
252
          path_from_line_rects (cr, (GdkRectangle *)lines->data, lines->len);
 
253
 
 
254
          /* For some reason we need to copy and reapply the path, or it gets
 
255
             eaten by gtk_render_background() */
 
256
          path = cairo_copy_path (cr);
 
257
 
 
258
          cairo_save (cr);
 
259
          cairo_clip (cr);
 
260
          gtk_widget_get_allocation (widget, &allocation);
 
261
          gtk_render_background (context, cr,
 
262
                                 0, 0,
 
263
                                 allocation.width, allocation.height);
 
264
          cairo_restore (cr);
 
265
 
 
266
          cairo_append_path (cr, path);
 
267
          cairo_path_destroy (path);
 
268
 
 
269
          state = gtk_widget_get_state_flags (widget);
 
270
          gtk_style_context_get_border_color (context,
 
271
                                              state,
 
272
                                              &border_color);
 
273
          gtk_style_context_get_border (context, state,
 
274
                                        &border);
 
275
 
 
276
          cairo_set_line_width (cr, border.left);
 
277
          gdk_cairo_set_source_rgba (cr, &border_color);
 
278
          cairo_stroke (cr);
 
279
        }
 
280
      g_array_free (lines, TRUE);
 
281
 
 
282
      gtk_tree_path_free (path);
 
283
 
 
284
      gtk_style_context_restore (context);
 
285
      cairo_restore (cr);
 
286
    }
 
287
 
 
288
  return FALSE;
 
289
}
 
290
 
 
291
static void
 
292
gd_main_icon_view_class_init (GdMainIconViewClass *klass)
 
293
{
 
294
  GObjectClass *oclass = G_OBJECT_CLASS (klass);
 
295
  GtkWidgetClass *wclass = GTK_WIDGET_CLASS (klass);
 
296
  GtkBindingSet *binding_set;
 
297
  GdkModifierType activate_modifiers[] = { GDK_SHIFT_MASK, GDK_CONTROL_MASK, GDK_SHIFT_MASK | GDK_CONTROL_MASK };
 
298
  int i;
 
299
 
 
300
  binding_set = gtk_binding_set_by_class (klass);
 
301
 
 
302
  oclass->constructed = gd_main_icon_view_constructed;
 
303
  wclass->drag_data_get = gd_main_icon_view_drag_data_get;
 
304
  wclass->draw = gd_main_icon_view_draw;
 
305
 
 
306
  gtk_widget_class_install_style_property (wclass,
 
307
                                           g_param_spec_int ("check-icon-size",
 
308
                                                             "Check icon size",
 
309
                                                             "Check icon size",
 
310
                                                             -1, G_MAXINT, 40,
 
311
                                                             G_PARAM_READWRITE));
 
312
 
 
313
  g_type_class_add_private (klass, sizeof (GdMainIconViewPrivate));
 
314
 
 
315
 
 
316
  for (i = 0; i < G_N_ELEMENTS (activate_modifiers); i++)
 
317
    {
 
318
      gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, activate_modifiers[i],
 
319
                                    "activate-cursor-item", 0);
 
320
      gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, activate_modifiers[i],
 
321
                                    "activate-cursor-item", 0);
 
322
      gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, activate_modifiers[i],
 
323
                                    "activate-cursor-item", 0);
 
324
      gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, activate_modifiers[i],
 
325
                                    "activate-cursor-item", 0);
 
326
      gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, activate_modifiers[i],
 
327
                                    "activate-cursor-item", 0);
 
328
    }
 
329
}
 
330
 
 
331
static void
 
332
gd_main_icon_view_init (GdMainIconView *self)
 
333
{
 
334
  self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GD_TYPE_MAIN_ICON_VIEW, GdMainIconViewPrivate);
 
335
}
 
336
 
 
337
static GtkTreePath *
 
338
gd_main_icon_view_get_path_at_pos (GdMainViewGeneric *mv,
 
339
                                   gint x,
 
340
                                   gint y)
 
341
{
 
342
  return gtk_icon_view_get_path_at_pos (GTK_ICON_VIEW (mv), x, y);
 
343
}
 
344
 
 
345
static void
 
346
gd_main_icon_view_set_selection_mode (GdMainViewGeneric *mv,
 
347
                                      gboolean selection_mode)
 
348
{
 
349
  GdMainIconView *self = GD_MAIN_ICON_VIEW (mv);
 
350
 
 
351
  self->priv->selection_mode = selection_mode;
 
352
 
 
353
  g_object_set (self->priv->pixbuf_cell,
 
354
                "toggle-visible", selection_mode,
 
355
                NULL);
 
356
  gtk_widget_queue_draw (GTK_WIDGET (self));
 
357
}
 
358
 
 
359
static void
 
360
gd_main_icon_view_scroll_to_path (GdMainViewGeneric *mv,
 
361
                                  GtkTreePath *path)
 
362
{
 
363
  gtk_icon_view_scroll_to_path (GTK_ICON_VIEW (mv), path, TRUE, 0.5, 0.5);
 
364
}
 
365
 
 
366
static void
 
367
gd_main_icon_view_set_model (GdMainViewGeneric *mv,
 
368
                             GtkTreeModel *model)
 
369
{
 
370
  gtk_icon_view_set_model (GTK_ICON_VIEW (mv), model);
 
371
}
 
372
 
 
373
static GtkTreeModel *
 
374
gd_main_icon_view_get_model (GdMainViewGeneric *mv)
 
375
{
 
376
  return gtk_icon_view_get_model (GTK_ICON_VIEW (mv));
 
377
}
 
378
 
 
379
static void
 
380
gd_main_view_generic_iface_init (GdMainViewGenericIface *iface)
 
381
{
 
382
  iface->set_model = gd_main_icon_view_set_model;
 
383
  iface->get_model = gd_main_icon_view_get_model;
 
384
  iface->get_path_at_pos = gd_main_icon_view_get_path_at_pos;
 
385
  iface->scroll_to_path = gd_main_icon_view_scroll_to_path;
 
386
  iface->set_selection_mode = gd_main_icon_view_set_selection_mode;
 
387
}
 
388
 
 
389
GtkWidget *
 
390
gd_main_icon_view_new (void)
 
391
{
 
392
  return g_object_new (GD_TYPE_MAIN_ICON_VIEW, NULL);
 
393
}