[gnome-contacts] Use a dialog for avatar changing
- From: Alexander Larsson <alexl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-contacts] Use a dialog for avatar changing
- Date: Thu, 2 Feb 2012 19:12:09 +0000 (UTC)
commit 934fb57707d4e533e80dc13af12ec398acc52c66
Author: Alexander Larsson <alexl redhat com>
Date: Thu Feb 2 20:09:49 2012 +0100
Use a dialog for avatar changing
This is according to the new mockup
po/POTFILES.in | 2 +-
src/Makefile.am | 3 +-
src/contacts-avatar-dialog.vala | 301 +++++++++++++++++++++++++++++++++++++++
src/contacts-avatar-menu.vala | 193 -------------------------
src/contacts-contact-frame.vala | 157 +++-----------------
src/contacts-contact-pane.vala | 44 ++++---
src/contacts-utils.vala | 21 +++
src/memory-icon.vala | 88 ++++++++++++
8 files changed, 461 insertions(+), 348 deletions(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 6ba3db8..2ab8b5f 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -1,7 +1,7 @@
data/gnome-contacts.desktop.in.in
[type: gettext/glade]src/app-menu.ui
src/contacts-app.vala
-src/contacts-avatar-menu.vala
+src/contacts-avatar-dialog.vala
src/contacts-contact-pane.vala
src/contacts-contact.vala
src/contacts-esd-setup.c
diff --git a/src/Makefile.am b/src/Makefile.am
index d6ff529..cbb0e73 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -32,12 +32,13 @@ vala_sources = \
contacts-utils.vala \
contacts-clickable.vala \
contacts-new-contact-dialog.vala \
- contacts-avatar-menu.vala \
+ contacts-avatar-dialog.vala \
contacts-contact-frame.vala \
contacts-revealer.vala \
contacts-setup-window.vala \
contacts-window.vala \
main.vala \
+ memory-icon.vala \
$(NULL)
gsettingsschema_in_files = org.gnome.Contacts.gschema.xml.in
diff --git a/src/contacts-avatar-dialog.vala b/src/contacts-avatar-dialog.vala
new file mode 100644
index 0000000..5d0355b
--- /dev/null
+++ b/src/contacts-avatar-dialog.vala
@@ -0,0 +1,301 @@
+/* -*- Mode: vala; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 8 -*- */
+/*
+ * Copyright (C) 2011 Alexander Larsson <alexl redhat com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+using Gtk;
+using Folks;
+
+public class Contacts.AvatarDialog : Dialog {
+ private Gnome.DesktopThumbnailFactory thumbnail_factory;
+ const int main_size = 96;
+ const int icons_size = 64;
+ private Contact contact;
+ private Grid view_grid;
+ private ContactFrame main_frame;
+
+ private Gdk.Pixbuf? new_pixbuf;
+
+ public signal void set_avatar (GLib.Icon avatar_icon);
+
+ Gdk.Pixbuf scale_pixbuf_for_avatar_use (Gdk.Pixbuf pixbuf) {
+ int w = pixbuf.get_width ();
+ int h = pixbuf.get_height ();
+
+ if (w <= 128 && h <= 128)
+ return pixbuf;
+
+ if (w > h) {
+ h = (int)Math.round (h * 128.0 / w);
+ w = 128;
+ } else {
+ w = (int)Math.round (w * 128.0 / h);
+ h = 128;
+ }
+
+ return pixbuf.scale_simple (w, h, Gdk.InterpType.HYPER);
+ }
+
+ private ContactFrame create_frame (Gdk.Pixbuf source_pixbuf) {
+ var image_frame = new ContactFrame (icons_size, true);
+ var pixbuf = source_pixbuf.scale_simple (icons_size, icons_size, Gdk.InterpType.HYPER);
+ image_frame.set_pixbuf (pixbuf);
+ var avatar_pixbuf = scale_pixbuf_for_avatar_use (source_pixbuf);
+ image_frame.clicked.connect ( () => {
+ selected_pixbuf (avatar_pixbuf);
+ });
+ return image_frame;
+ }
+
+ private ContactFrame? frame_for_persona (Persona persona) {
+ var details = persona as AvatarDetails;
+ if (details == null || details.avatar == null)
+ return null;
+
+ try {
+ var stream = details.avatar.load (128, null);
+ var pixbuf = new Gdk.Pixbuf.from_stream (stream);
+ return create_frame (pixbuf);
+ }
+ catch {
+ }
+
+ return null;
+ }
+
+ private ContactFrame? frame_for_filename (string filename) {
+ ContactFrame? image_frame = null;
+ try {
+ var pixbuf = new Gdk.Pixbuf.from_file (filename);
+ return create_frame (pixbuf);
+ } catch {
+ }
+ return image_frame;
+ }
+
+ private void selected_pixbuf (Gdk.Pixbuf pixbuf) {
+ try {
+ var p = pixbuf.scale_simple (main_size, main_size, Gdk.InterpType.HYPER);
+ main_frame.set_pixbuf (p);
+
+ new_pixbuf = pixbuf;
+ } catch {
+ }
+ }
+
+ private void update_grid () {
+ int i = 0;
+ int j = 0;
+
+ foreach (var p in contact.individual.personas) {
+ ContactFrame? frame = frame_for_persona (p);
+ if (frame != null) {
+ view_grid.attach (frame, i, j, 1, 1);
+ i++;
+ if (i >= 4) {
+ i -= 4;
+ j++;
+ }
+ }
+ }
+
+ if (i != 0) {
+ i = 0;
+ j++;
+ }
+
+ if (j != 0) {
+ var s = new Separator (Orientation.HORIZONTAL);
+ view_grid.attach (s, 0, j++, 4, 1);
+ }
+
+ var stock_files = Utils.get_stock_avatars ();
+ foreach (var file_name in stock_files) {
+ ContactFrame? frame = frame_for_filename (file_name);
+ if (frame != null) {
+ view_grid.attach (frame, i, j, 1, 1);
+ i++;
+ if (i >= 4) {
+ i -= 4;
+ j++;
+ }
+ }
+ }
+
+ view_grid.show_all ();
+ }
+
+ public void update_preview (FileChooser chooser) {
+ var uri = chooser.get_preview_uri ();
+ if (uri != null) {
+ Gdk.Pixbuf? pixbuf = null;
+
+ var preview = chooser.get_preview_widget () as Image;
+
+ var file = File.new_for_uri (uri);
+ try {
+ var file_info = file.query_info (GLib.FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
+ FileQueryInfoFlags.NONE, null);
+ if (file_info != null) {
+ var mime_type = file_info.get_content_type ();
+
+ if (mime_type != null)
+ pixbuf = thumbnail_factory.generate_thumbnail (uri, mime_type);
+ }
+ } catch (GLib.Error e) {
+ }
+
+ (chooser as Dialog).set_response_sensitive (ResponseType.ACCEPT,
+ (pixbuf != null));
+
+ if (pixbuf != null)
+ preview.set_from_pixbuf (pixbuf);
+ else
+ preview.set_from_stock (Stock.DIALOG_QUESTION,
+ IconSize.DIALOG);
+ }
+
+ chooser.set_preview_widget_active (true);
+ }
+
+ private void select_avatar_file_cb () {
+ var chooser = new FileChooserDialog (_("Browse for more pictures"),
+ (Window)this.get_toplevel (),
+ FileChooserAction.OPEN,
+ Stock.CANCEL, ResponseType.CANCEL,
+ Stock.OPEN, ResponseType.ACCEPT);
+ chooser.set_modal (true);
+ chooser.set_local_only (false);
+ var preview = new Image ();
+ preview.set_size_request (128, -1);
+ chooser.set_preview_widget (preview);
+ chooser.set_use_preview_label (false);
+ preview.show ();
+
+ chooser.update_preview.connect (update_preview);
+
+ var folder = Environment.get_user_special_dir (UserDirectory.PICTURES);
+ if (folder != null)
+ chooser.set_current_folder (folder);
+
+ chooser.response.connect ( (response) => {
+ if (response != ResponseType.ACCEPT) {
+ chooser.destroy ();
+ return;
+ }
+ try {
+ var file = File.new_for_uri (chooser.get_uri ());
+ var in_stream = file.read ();
+ var pixbuf = new Gdk.Pixbuf.from_stream (in_stream, null);
+ in_stream.close ();
+ selected_pixbuf (scale_pixbuf_for_avatar_use (pixbuf));
+ } catch {
+ }
+
+ chooser.destroy ();
+ });
+
+ chooser.present ();
+ }
+
+
+ public AvatarDialog (Contact contact) {
+ thumbnail_factory = new Gnome.DesktopThumbnailFactory (Gnome.ThumbnailSize.NORMAL);
+ this.contact = contact;
+ set_title (_("Select Picture"));
+ set_transient_for (App.app.window);
+ set_modal (true);
+ add_buttons (_("Close"), ResponseType.CLOSE, null);
+
+ var grid = new Grid ();
+ grid.set_border_width (8);
+ grid.set_column_spacing (8);
+ var container = (get_content_area () as Container);
+ container.add (grid);
+
+ main_frame = new ContactFrame (main_size);
+ contact.keep_widget_uptodate (main_frame, (w) => {
+ (w as ContactFrame).set_image (contact.individual, contact);
+ });
+ main_frame.set_hexpand (false);
+ grid.attach (main_frame, 0, 0, 1, 1);
+
+ var label = new Label ("");
+ label.set_markup ("<span font='13'>" + contact.display_name + "</span>");
+ label.set_valign (Align.START);
+ label.set_halign (Align.START);
+ label.set_hexpand (true);
+ label.xalign = 0.0f;
+ label.set_ellipsize (Pango.EllipsizeMode.END);
+ grid.attach (label, 1, 0, 1, 1);
+
+ grid.set_row_spacing (18);
+
+ var frame = new Frame (null);
+ grid.attach (frame, 0, 1, 2, 1);
+ var frame_grid = new Grid ();
+ frame_grid.set_orientation (Orientation.VERTICAL);
+ frame.add (frame_grid);
+
+ var scrolled = new ScrolledWindow(null, null);
+ scrolled.set_policy (PolicyType.NEVER, PolicyType.AUTOMATIC);
+ scrolled.set_vexpand (true);
+ scrolled.set_hexpand (true);
+ scrolled.set_size_request (-1, 300);
+
+ frame_grid.add (scrolled);
+
+ view_grid = new Grid ();
+ scrolled.add_with_viewport (view_grid);
+
+ var toolbar = new Toolbar ();
+ toolbar.get_style_context ().add_class (STYLE_CLASS_PRIMARY_TOOLBAR);
+ toolbar.set_icon_size (IconSize.MENU);
+ toolbar.set_vexpand (false);
+ frame_grid.add (toolbar);
+
+ var add_button = new ToolButton (null, null);
+ add_button.set_icon_name ("list-add-symbolic");
+ add_button.get_style_context ().add_class (STYLE_CLASS_RAISED);
+ add_button.is_important = true;
+ toolbar.add (add_button);
+ add_button.clicked.connect (select_avatar_file_cb);
+
+ /*
+ var remove_button = new ToolButton (null, null);
+ remove_button.set_icon_name ("list-remove-symbolic");
+ remove_button.get_style_context ().add_class (STYLE_CLASS_RAISED);
+ remove_button.is_important = true;
+ toolbar.add (remove_button);
+ remove_button.clicked.connect ( (button) => {
+ });
+ */
+
+ response.connect ( (response_id) => {
+ if (response_id == ResponseType.CLOSE) {
+ if (new_pixbuf != null) {
+ var icon = new MemoryIcon.from_pixbuf (new_pixbuf);
+ set_avatar (icon);
+ }
+ }
+ this.destroy ();
+ });
+
+ update_grid ();
+
+ grid.show_all ();
+ }
+}
diff --git a/src/contacts-contact-frame.vala b/src/contacts-contact-frame.vala
index 0c4bc82..59dfe09 100644
--- a/src/contacts-contact-frame.vala
+++ b/src/contacts-contact-frame.vala
@@ -26,143 +26,28 @@ public class Contacts.ContactFrame : Frame {
private Gdk.Pixbuf? pixbuf;
private Pango.Layout? layout;
private int text_height;
- private bool popup_in_progress;
- private Gtk.Menu? menu;
- private void menu_position (Gtk.Menu menu, out int x, out int y, out bool push_in) {
- Allocation allocation;
- get_allocation (out allocation);
+ public signal void clicked ();
- int sx = 0;
- int sy = 0;
-
- if (!get_has_window ()) {
- sx += allocation.x;
- sy += allocation.y;
- }
-
- get_window ().get_root_coords (sx, sy, out sx, out sy);
-
- Requisition menu_req;
- Gdk.Rectangle monitor;
-
- menu.get_preferred_size (null, out menu_req);
-
- if (get_direction () == TextDirection.LTR)
- x = sx + 2;
- else
- x = sx + allocation.width - menu_req.width - 2;
- y = sy - 2;
-
- var window = get_window ();
- var screen = get_screen ();
- var monitor_num = screen.get_monitor_at_window (window);
- if (monitor_num < 0)
- monitor_num = 0;
- screen.get_monitor_geometry (monitor_num, out monitor);
-
- if (x < monitor.x)
- x = monitor.x;
- else if (x + menu_req.width > monitor.x + monitor.width)
- x = monitor.x + monitor.width - menu_req.width;
-
- if (monitor.y + monitor.height - y - allocation.height >= menu_req.height)
- y += allocation.height;
- else if (y - monitor.y >= menu_req.height)
- y -= menu_req.height;
- else if (monitor.y + monitor.height - y - allocation.height > y - monitor.y)
- y += allocation.height;
- else
- y -= menu_req.height;
-
- menu.set_monitor (monitor_num);
-
- Window? toplevel = menu.get_parent() as Window;
- if (toplevel != null && !toplevel.get_visible())
- toplevel.set_type_hint (Gdk.WindowTypeHint.DROPDOWN_MENU);
-
- push_in = false;
- }
-
- public ContactFrame (int size, Gtk.Menu? menu = null) {
+ public ContactFrame (int size, bool with_button = false) {
this.size = size;
var image = new Image ();
image.set_size_request (size, size);
- this.menu = menu;
-
- var button = new ToggleButton ();
- button.set_focus_on_click (false);
- button.get_style_context ().add_class ("contacts-frame-button");
- button.add (image);
- button.set_mode (false);
- this.add (button);
-
- button.toggled.connect ( () => {
- if (this.menu == null) {
- if (button.get_active ())
- button.set_active (false);
- return;
- }
-
- if (button.get_active ()) {
- if (!popup_in_progress) {
- menu.popup (null, null, menu_position, 1, Gtk.get_current_event_time ());
- }
- } else {
- menu.popdown ();
- }
- });
-
- button.button_press_event.connect ( (event) => {
- if (this.menu == null)
- return true;
- var ewidget = Gtk.get_event_widget ((Gdk.Event)(&event));
-
- if (ewidget != button ||
- button.get_active ())
- return false;
-
- menu.popup (null, null, menu_position, 1, Gtk.get_current_event_time ());
- button.set_active (true);
- popup_in_progress = true;
- return true;
- });
-
- button.button_release_event.connect ( (event) => {
- if (this.menu == null)
- return false;
-
- bool popup_in_progress_saved = popup_in_progress;
- popup_in_progress = false;
-
- var ewidget = Gtk.get_event_widget ((Gdk.Event)(&event));
-
- if (ewidget == button &&
- !popup_in_progress_saved &&
- button.get_active ()) {
- menu.popdown ();
- return true;
- }
- if (ewidget != button) {
- menu.popdown ();
- return true;
- }
- return false;
- });
-
- if (menu != null) {
- menu.show.connect ( (menu) => {
- popup_in_progress = true;
- button.set_active (true);
- popup_in_progress = false;
- });
- menu.hide.connect ( (menu) => {
- button.set_active (false);
- });
- menu.attach_to_widget (button, (menu) => {
+ if (with_button) {
+ var button = new Button ();
+ button.set_relief (ReliefStyle.NONE);
+ button.set_focus_on_click (false);
+ button.add (image);
+
+ button.clicked.connect ( () => {
+ this.clicked ();
});
+
+ this.add (button);
+ } else {
+ this.add (image);
}
image.show ();
@@ -171,23 +56,27 @@ public class Contacts.ContactFrame : Frame {
set_shadow_type (ShadowType.NONE);
}
+ public void set_pixbuf (Gdk.Pixbuf a_pixbuf) {
+ pixbuf = Contact.frame_icon (a_pixbuf);
+ queue_draw ();
+ }
+
public void set_image (AvatarDetails? details, Contact? contact = null) {
- pixbuf = null;
+ Gdk.Pixbuf? a_pixbuf = null;
if (details != null &&
details.avatar != null) {
try {
var stream = details.avatar.load (size, null);
- pixbuf = new Gdk.Pixbuf.from_stream_at_scale (stream, size, size, true);
+ a_pixbuf = new Gdk.Pixbuf.from_stream_at_scale (stream, size, size, true);
}
catch {
}
}
- if (pixbuf == null) {
- pixbuf = Contact.draw_fallback_avatar (size, contact);
+ if (a_pixbuf == null) {
+ a_pixbuf = Contact.draw_fallback_avatar (size, contact);
}
- pixbuf = Contact.frame_icon (pixbuf);
- queue_draw ();
+ set_pixbuf (a_pixbuf);
}
public void set_text (string? text_, int text_height_) {
diff --git a/src/contacts-contact-pane.vala b/src/contacts-contact-pane.vala
index 022c84e..96fb247 100644
--- a/src/contacts-contact-pane.vala
+++ b/src/contacts-contact-pane.vala
@@ -1482,6 +1482,25 @@ public class Contacts.ContactPane : ScrolledWindow {
return null;
}
+ private void change_avatar (ContactFrame image_frame) {
+ var dialog = new AvatarDialog (contact);
+ dialog.show_all ();
+ dialog.set_avatar.connect ( (icon) => {
+ Value v = Value (icon.get_type ());
+ v.set_object (icon);
+ set_individual_property.begin (contact,
+ "avatar", v,
+ (obj, result) => {
+ try {
+ var p = set_individual_property.end (result);
+ } catch (Error e) {
+ App.app.show_message (e.message);
+ image_frame.set_image (contact.individual, contact);
+ }
+ });
+ });
+ }
+
public void update_card () {
foreach (var w in card_grid.get_children ()) {
w.destroy ();
@@ -1490,23 +1509,10 @@ public class Contacts.ContactPane : ScrolledWindow {
if (contact == null)
return;
- var menu = new AvatarMenu (contact);
- var image_frame = new ContactFrame (PROFILE_SIZE, menu);
- menu.icon_set.connect ( (icon) => {
- Value v = Value (icon.get_type ());
- v.set_object (icon);
- set_individual_property.begin (contact,
- "avatar", v,
- (obj, result) => {
- try {
- var p = set_individual_property.end (result);
- } catch (Error e) {
- App.app.show_message (e.message);
- image_frame.set_image (contact.individual, contact);
- }
- });
+ var image_frame = new ContactFrame (PROFILE_SIZE, true);
+ image_frame.clicked.connect ( () => {
+ change_avatar (image_frame);
});
-
contact.keep_widget_uptodate (image_frame, (w) => {
(w as ContactFrame).set_image (contact.individual, contact);
});
@@ -1708,7 +1714,7 @@ public class Contacts.ContactPane : ScrolledWindow {
}
public signal void contacts_linked (string main_contact, string linked_contact, LinkOperation operation);
-
+
public void add_suggestion (Contact c) {
var row = new FieldRow (row_group);
personas_grid.add (row);
@@ -1756,8 +1762,8 @@ public class Contacts.ContactPane : ScrolledWindow {
var main_contact = contact.display_name;
var linked_contact = c.display_name;
link_contacts.begin (contact, c, (obj, result) => {
- var operation = link_contacts.end (result);
- this.contacts_linked (main_contact, linked_contact, operation);
+ var operation = link_contacts.end (result);
+ this.contacts_linked (main_contact, linked_contact, operation);
});
row.destroy ();
});
diff --git a/src/contacts-utils.vala b/src/contacts-utils.vala
index 774ddf9..6c5b7db 100644
--- a/src/contacts-utils.vala
+++ b/src/contacts-utils.vala
@@ -242,4 +242,25 @@ public class Contacts.Utils : Object {
spawn_app (calendar_settings);
}
}
+
+ public static string[] get_stock_avatars () {
+ string[] files = {};
+ var system_data_dirs = Environment.get_system_data_dirs ();
+ foreach (var data_dir in system_data_dirs) {
+ var path = Path.build_filename (data_dir, "pixmaps", "faces");
+ Dir? dir = null;
+ try {
+ dir = Dir.open (path);
+ } catch {
+ }
+ if (dir != null) {
+ string? face;
+ while ((face = dir.read_name ()) != null) {
+ var filename = Path.build_filename (path, face);
+ files += filename;
+ }
+ }
+ };
+ return files;
+ }
}
diff --git a/src/memory-icon.vala b/src/memory-icon.vala
new file mode 100644
index 0000000..febb700
--- /dev/null
+++ b/src/memory-icon.vala
@@ -0,0 +1,88 @@
+/* -*- Mode: vala; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 8 -*- */
+/*
+ * Copyright (C) 2011 Philip Withnall
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Philip Withnall <philip tecnocode co uk>
+ */
+
+using GLib;
+
+/**
+ * A wrapper around a blob of image data (with an associated content type) which
+ * presents it as a { link GLib.LoadableIcon}. This allows inlined avatars to be
+ * returned as { link GLib.LoadableIcon}s.
+ */
+internal class Contacts.MemoryIcon : Object, Icon, LoadableIcon {
+ private uint8[] _image_data;
+ private string? _image_type;
+
+ public MemoryIcon (string? image_type, uint8[] image_data) {
+ this._image_data = image_data;
+ this._image_type = image_type;
+ }
+
+ public MemoryIcon.from_pixbuf (Gdk.Pixbuf pixbuf) throws GLib.Error {
+ uint8[] buffer;
+ if (pixbuf.save_to_buffer (out buffer, "png", null)) {
+ this ("image/png", buffer);
+ }
+ }
+
+#if VALA_0_16
+ public bool equal (Icon? icon2)
+#else
+ public bool equal (Icon icon2)
+#endif
+ {
+ /* These type and nullability checks are taken care of by the interface
+ * wrapper. */
+ var icon = (MemoryIcon) (!) icon2;
+ return (this._image_data.length == icon._image_data.length &&
+ Memory.cmp (this._image_data, icon._image_data,
+ this._image_data.length) == 0);
+ }
+
+ public uint hash () {
+ /* Implementation based on g_str_hash() from GLib. We initialise the hash
+ * with the g_str_hash() hash of the image type (which itself is
+ * initialised with the magic number in GLib thought up by cleverer people
+ * than myself), then add each byte in the image data to the hash value
+ * by multiplying the hash value by 33 and adding the image data, as is
+ * done on all bytes in g_str_hash(). I leave the rationale for this
+ * calculation to the author of g_str_hash().
+ *
+ * Basically, this is just a nul-safe version of g_str_hash(). Which is
+ * calculated over both the image type and image data. */
+ uint hash = this._image_type != null ? ((!) this._image_type).hash () : 0;
+ for (uint i = 0; i < this._image_data.length; i++) {
+ hash = (hash << 5) + hash + this._image_data[i];
+ }
+
+ return hash;
+ }
+
+ public InputStream load (int size, out string? type,
+ Cancellable? cancellable = null) {
+ type = this._image_type;
+ return new MemoryInputStream.from_data (this._image_data, free);
+ }
+
+ public async InputStream load_async (int size, GLib.Cancellable? cancellable, out string? type) {
+ type = this._image_type;
+ return new MemoryInputStream.from_data (this._image_data, free);
+ }
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]