[helpers] split up helpers to gui and non gui parts.

This commit is contained in:
Hylke Bons 2010-09-04 13:27:06 +01:00
parent 71cfc24642
commit 1644c5c5f2
12 changed files with 289 additions and 336 deletions

View file

@ -10,7 +10,7 @@ Contributors:
Benjamin Podszun <benjamin.podszun@gmail.com>
Bertrand Lorentz <bertrand.lorentz@gmail.com>
Garrett LeSage <garrett@novell.com>
Jakub Steiner <jimmac@novell.com>
Jakub Steiner <jimmac@redhat.com>
Lapo Calamandrei <calamandrei@gmail.com>
Łukasz Jernaś <deejay1@srem.org>
Michael Monreal <michael.monreal@gmail.com>
@ -21,5 +21,6 @@ Contributors:
Sandy Armstrong <sanfordarmstrong@gmail.com>
Simon Pither <simon@pither.com>
Steven Harms <sharms@ubuntu.com>
Vincent Untz <vuntz@gnome.org>
Thanks very much!

View file

@ -5,9 +5,10 @@ LINK = $(REF_SPARKLELIB)
SOURCES = \
Defines.cs \
SparkleOptions.cs \
SparkleEvents.cs \
SparkleFetcher.cs \
SparkleHelpers.cs \
SparkleOptions.cs \
SparklePaths.cs \
SparklePlatform.cs \
SparkleRepo.cs

View file

@ -14,176 +14,46 @@
// 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 Mono.Unix;
using System;
using System.IO;
using System.Net;
using System.Security.Cryptography;
using System.Text;
namespace SparkleLib {
public static class SparkleHelpers
{
// Gets the avatar for a specific email address and size
public static Gdk.Pixbuf GetAvatar (string Email, int Size)
{
string AvatarPath = CombineMore (SparklePaths.SparkleLocalIconPath, Size + "x" + Size, "status");
if (!Directory.Exists (AvatarPath)) {
Directory.CreateDirectory (AvatarPath);
SparkleHelpers.DebugInfo ("Config", "Created '" + AvatarPath + "'");
}
string AvatarFilePath = CombineMore (AvatarPath, "avatar-" + Email);
if (File.Exists (AvatarFilePath))
return new Gdk.Pixbuf (AvatarFilePath);
else {
// Let's try to get the person's gravatar for next time
WebClient WebClient = new WebClient ();
Uri GravatarUri = new Uri ("http://www.gravatar.com/avatar/" + GetMD5 (Email) +
".jpg?s=" + Size + "&d=404");
string TmpFile = CombineMore (SparklePaths.SparkleTmpPath, Email + Size);
if (!File.Exists (TmpFile)) {
WebClient.DownloadFileAsync (GravatarUri, TmpFile);
WebClient.DownloadFileCompleted += delegate {
File.Delete (AvatarFilePath);
FileInfo TmpFileInfo = new FileInfo (TmpFile);
if (TmpFileInfo.Length > 255)
File.Move (TmpFile, AvatarFilePath);
};
}
// Fall back to a generic icon if there is no gravatar
if (File.Exists (AvatarFilePath))
return new Gdk.Pixbuf (AvatarFilePath);
else
return GetIcon ("avatar-default", Size);
}
}
// Creates an MD5 hash of input
public static string GetMD5 (string s)
{
MD5 md5 = new MD5CryptoServiceProvider ();
Byte[] bytes = ASCIIEncoding.Default.GetBytes (s);
Byte[] encodedBytes = md5.ComputeHash (bytes);
return BitConverter.ToString (encodedBytes).ToLower ().Replace ("-", "");
}
// Makes it possible to combine more than
// two paths at once
public static string CombineMore (params string [] Parts)
{
string NewPath = " ";
foreach (string Part in Parts)
NewPath = Path.Combine (NewPath, Part);
return NewPath;
}
// Looks up an icon from the system's theme
public static Gdk.Pixbuf GetIcon (string name, int size)
{
IconTheme IconTheme = new IconTheme ();
IconTheme.AppendSearchPath (SparklePaths.SparkleIconPath);
IconTheme.AppendSearchPath (SparklePaths.SparkleLocalIconPath);
try {
return IconTheme.LoadIcon (name, size, IconLookupFlags.GenericFallback);
} catch {
try {
return IconTheme.LoadIcon ("gtk-missing-image", size, IconLookupFlags.GenericFallback);
} catch {
return null;
}
}
}
public static bool ShowDebugInfo = true;
// Show debug info if needed
public static void DebugInfo (string Type, string Message)
public static void DebugInfo (string type, string message)
{
if (ShowDebugInfo) {
DateTime DateTime = new DateTime ();
string TimeStamp = DateTime.Now.ToString ("HH:mm:ss");
if (Message.StartsWith ("["))
Console.WriteLine ("[" + TimeStamp + "]" + "[" + Type + "]" + Message);
string timestamp = DateTime.Now.ToString ("HH:mm:ss");
if (message.StartsWith ("["))
Console.WriteLine ("[" + timestamp + "]" + "[" + type + "]" + message);
else
Console.WriteLine ("[" + TimeStamp + "]" + "[" + Type + "] " + Message);
Console.WriteLine ("[" + timestamp + "]" + "[" + type + "] " + message);
}
}
// Formats a timestamp to a relative date compared to the current time
// Example: "about 5 hours ago"
public static string ToRelativeDate (DateTime date_time)
// Makes it possible to combine more than
// two paths at once
public static string CombineMore (params string [] parts)
{
TimeSpan time_span = new TimeSpan (0);
time_span = DateTime.Now - date_time;
string new_path = "";
if (time_span <= TimeSpan.FromSeconds (60)) {
return string.Format (Catalog.GetPluralString ("a second ago", "{0} seconds ago",
time_span.Seconds),
time_span.Seconds);
}
foreach (string part in parts)
new_path = Path.Combine (new_path, part);
if (time_span <= TimeSpan.FromSeconds (60)) {
return string.Format (Catalog.GetPluralString ("a minute ago", "about {0} minutes ago",
time_span.Minutes),
time_span.Minutes);
}
if (time_span <= TimeSpan.FromHours (24)) {
return string.Format (Catalog.GetPluralString ("about an hour ago", "about {0} hours ago",
time_span.Hours),
time_span.Hours);
}
if (time_span <= TimeSpan.FromDays (30)) {
return string.Format (Catalog.GetPluralString ("yesterday", "{0} days ago",
time_span.Days),
time_span.Days);
}
if (time_span <= TimeSpan.FromDays (365)) {
return string.Format (Catalog.GetPluralString ("a month ago", "{0} months ago",
(int) time_span.Days / 30),
(int) time_span.Days / 30);
}
return string.Format (Catalog.GetPluralString ("a year ago", "{0} years ago",
(int) time_span.Days / 365),
(int) time_span.Days / 365);
return new_path;
}

View file

@ -30,9 +30,6 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="gtk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
<Package>gtk-sharp-2.0</Package>
</Reference>
<Reference Include="Mono.Posix" />
</ItemGroup>
<ItemGroup>
@ -42,6 +39,8 @@
<Compile Include="SparkleHelpers.cs" />
<Compile Include="SparklePaths.cs" />
<Compile Include="SparklePlatform.cs" />
<Compile Include="SparkleEvents.cs" />
<Compile Include="SparkleOptions.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ProjectExtensions>

View file

@ -775,40 +775,4 @@ namespace SparkleLib {
}
// Arguments for most events
public class SparkleEventArgs : System.EventArgs {
public string Type;
public string Message;
public SparkleEventArgs (string type)
{
Type = type;
}
}
// Arguments for the NewCommit event
public class NewCommitArgs : System.EventArgs {
public string Author;
public string Email;
public string Message;
public string RepositoryName;
public NewCommitArgs (string author, string email, string message, string repository_name)
{
Author = author;
Email = email;
Message = message;
RepositoryName = repository_name;
}
}
}

View file

@ -18,6 +18,7 @@ SOURCES = \
SparkleSpinner.cs \
SparkleStatusIcon.cs \
SparkleUI.cs \
SparkleUIHelpers.cs \
SparkleWindow.cs
include $(top_srcdir)/build/build.mk

View file

@ -172,7 +172,7 @@ namespace SparkleShare {
HBox layout_server = new HBox (true, 0);
ServerEntry = new SparkleEntry () {
ExampleText = _("ssh://address-to-my-server/")
ExampleText = _("address-to-server.com")
};
ServerEntry.Changed += CheckServerForm;
@ -295,9 +295,18 @@ namespace SparkleShare {
if (name.EndsWith ("/"))
name = name.TrimEnd ("/".ToCharArray ());
if (name.StartsWith ("/"))
name = name.TrimStart ("/".ToCharArray ());
if (radio_button.Active) {
server = SparkleToGitUrl (ServerEntry.Text);
// Use the default user 'git' if no username is specified
if (!server.Contains ("@"))
server = "git@" + server;
// Prepend the Secure Shell protocol when it isn't specified
if (!server.StartsWith ("ssh://"))
server = "ssh://" + server;
// Remove the trailing slash if there is one
if (server.EndsWith ("/"))
@ -368,6 +377,7 @@ namespace SparkleShare {
}
// The page shown when syncing has failed
private void ShowErrorPage ()
{
@ -401,54 +411,56 @@ namespace SparkleShare {
}
// The page shown when syncing has succeeded
private void ShowSuccessPage (string name)
{
Reset ();
VBox layout_vertical = new VBox (false, 0);
VBox layout_vertical = new VBox (false, 0);
Label header = new Label ("<span size='x-large'><b>" +
_("Folder synced successfully!") +
"</b></span>") {
UseMarkup = true,
Xalign = 0
};
Label information = new Label (_("Now you can access the synced files from " + name + " " +
"in your SparkleShare folder.")) {
Xalign = 0,
Wrap = true,
UseMarkup = true
};
Label header = new Label ("<span size='x-large'><b>" +
_("Folder synced successfully!") +
"</b></span>") {
UseMarkup = true,
Xalign = 0
};
Label information = new Label (_("Now you can access the synced files from " + name + " " +
"in your SparkleShare folder.")) {
Xalign = 0,
Wrap = true,
UseMarkup = true
};
Button open_folder_button = new Button (_("Open Folder"));
// A button that opens the synced folder
Button open_folder_button = new Button (_("Open Folder"));
open_folder_button.Clicked += delegate (object o, EventArgs args) {
open_folder_button.Clicked += delegate (object o, EventArgs args) {
string path = SparkleHelpers.CombineMore (SparklePaths.SparklePath, name);
string path = SparkleHelpers.CombineMore (SparklePaths.SparklePath, name);
Process process = new Process ();
process.StartInfo.FileName = "xdg-open";
process.StartInfo.Arguments = path.Replace (" ", "\\ "); // Escape space-characters
process.Start ();
Process process = new Process ();
process.StartInfo.FileName = "xdg-open";
process.StartInfo.Arguments = path.Replace (" ", "\\ "); // Escape space-characters
process.Start ();
if (ServerFormOnly)
Destroy ();
};
Button finish_button = new Button (_("Finish"));
finish_button.Clicked += delegate (object o, EventArgs args) {
if (ServerFormOnly)
Destroy ();
};
AddButton (open_folder_button);
AddButton (finish_button);
layout_vertical.PackStart (header, false, false, 0);
layout_vertical.PackStart (information, false, false, 21);
};
Button finish_button = new Button (_("Finish"));
finish_button.Clicked += delegate (object o, EventArgs args) {
Destroy ();
};
AddButton (open_folder_button);
AddButton (finish_button);
layout_vertical.PackStart (header, false, false, 0);
layout_vertical.PackStart (information, false, false, 21);
Add (layout_vertical);
@ -457,55 +469,56 @@ namespace SparkleShare {
}
// The page shown whilst syncing
private void ShowSyncingPage (string name)
{
Reset ();
VBox layout_vertical = new VBox (false, 0);
VBox layout_vertical = new VBox (false, 0);
Label header = new Label ("<span size='x-large'><b>" +
String.Format (_("Syncing folder {0}’…"), name) +
"</b></span>") {
UseMarkup = true,
Xalign = 0,
Wrap = true
};
Label information = new Label (_("This may take a while.\n") +
_("You sure its not coffee o-clock?")) {
UseMarkup = true,
Xalign = 0
};
Button button = new Button () {
Sensitive = false,
Label = _("Finish")
};
button.Clicked += delegate {
Destroy ();
};
AddButton (button);
SparkleSpinner spinner = new SparkleSpinner (22);
Table table = new Table (2, 2, false) {
RowSpacing = 12,
ColumnSpacing = 9
Label header = new Label ("<span size='x-large'><b>" +
String.Format (_("Syncing folder {0}’…"), name) +
"</b></span>") {
UseMarkup = true,
Xalign = 0,
Wrap = true
};
HBox box = new HBox (false, 0);
Label information = new Label (_("This may take a while.\n") +
_("You sure its not coffee o-clock?")) {
UseMarkup = true,
Xalign = 0
};
table.Attach (spinner, 0, 1, 0, 1);
table.Attach (header, 1, 2, 0, 1);
table.Attach (information, 1, 2, 1, 2);
box.PackStart (table, false, false, 0);
Button button = new Button () {
Sensitive = false,
Label = _("Finish")
};
button.Clicked += delegate {
Destroy ();
};
layout_vertical.PackStart (box, false, false, 0);
AddButton (button);
SparkleSpinner spinner = new SparkleSpinner (22);
Table table = new Table (2, 2, false) {
RowSpacing = 12,
ColumnSpacing = 9
};
HBox box = new HBox (false, 0);
table.Attach (spinner, 0, 1, 0, 1);
table.Attach (header, 1, 2, 0, 1);
table.Attach (information, 1, 2, 1, 2);
box.PackStart (table, false, false, 0);
layout_vertical.PackStart (box, false, false, 0);
Add (layout_vertical);
@ -514,6 +527,7 @@ namespace SparkleShare {
}
// The page shown when the setup has been completed
private void ShowCompletedPage ()
{
@ -572,9 +586,11 @@ namespace SparkleShare {
private void FetchFolder (string url, string name)
{
// Strip the '.git' from the name
string canonical_name = System.IO.Path.GetFileNameWithoutExtension (name);
string tmp_folder = SparkleHelpers.CombineMore (SparklePaths.SparkleTmpPath, canonical_name);
ShowSyncingPage (canonical_name);
SparkleFetcher fetcher = new SparkleFetcher (url, tmp_folder);
@ -643,8 +659,6 @@ namespace SparkleShare {
};
ShowSyncingPage (canonical_name);
fetcher.Clone ();
}
@ -806,19 +820,6 @@ namespace SparkleShare {
}
// Convert the more human readable sparkle:// url to something Git can use.
// Example: sparkle://gitorious.org/sparkleshare ssh://git@gitorious.org/sparkleshare
private static string SparkleToGitUrl (string url)
{
if (url.StartsWith ("sparkle://"))
url = url.Replace ("sparkle://", "ssh://git@");
return url;
}
}
}

View file

@ -290,10 +290,6 @@ namespace SparkleShare {
link.ModifyBg (StateType.Normal, background_color);
link.ButtonPressEvent += delegate {
Destroy ();
};
added_files.PackStart (link, false, false, 0);
}
@ -306,10 +302,6 @@ namespace SparkleShare {
link.ModifyBg (StateType.Normal, background_color);
link.ButtonPressEvent += delegate {
Destroy ();
};
deleted_files.PackStart (link, false, false, 0);
}
@ -321,19 +313,11 @@ namespace SparkleShare {
from_link.ModifyBg (StateType.Normal, background_color);
from_link.ButtonPressEvent += delegate {
Destroy ();
};
SparkleLink to_link = new SparkleLink (change_set.MovedTo [i],
SparkleHelpers.CombineMore (LocalPath, change_set.MovedTo [i]));
to_link.ModifyBg (StateType.Normal, background_color);
to_link.ButtonPressEvent += delegate {
Destroy ();
};
Label to_label = new Label ("<span fgcolor='" + secondary_text_color +"'>" +
"<small>to</small></span> ") {
UseMarkup = true,
@ -344,10 +328,11 @@ namespace SparkleShare {
link_wrapper.PackStart (to_label, false, false, 0);
link_wrapper.PackStart (to_link, true, true, 0);
moved_files.PackStart (from_link, false, false, 0);
moved_files.PackStart (link_wrapper, false, false, 0);
moved_files.PackStart (new Label (""), false, false, 0);
if (change_set.MovedFrom.Count > 1)
moved_files.PackStart (new Label (""), false, false, 0);
}
@ -419,7 +404,7 @@ namespace SparkleShare {
HBox hbox = new HBox (false, 0);
Image avatar = new Image (SparkleHelpers.GetAvatar (change_set.UserEmail, 32)) {
Image avatar = new Image (SparkleUIHelpers.GetAvatar (change_set.UserEmail, 32)) {
Yalign = 0
};
@ -452,7 +437,7 @@ namespace SparkleShare {
// Converts a UNIX timestamp to a more usable time object
public DateTime UnixTimestampToDateTime (int timestamp)
public static DateTime UnixTimestampToDateTime (int timestamp)
{
DateTime unix_epoch = new DateTime (1970, 1, 1, 0, 0, 0, 0);
return unix_epoch.AddSeconds (timestamp);
@ -461,7 +446,7 @@ namespace SparkleShare {
// Converts a Gdk RGB color to a hex value.
// Example: from "rgb:0,0,0" to "#000000"
public string GdkColorToHex (Gdk.Color color)
public static string GdkColorToHex (Gdk.Color color)
{
return String.Format ("#{0:X2}{1:X2}{2:X2}",
@ -481,16 +466,18 @@ namespace SparkleShare {
public ActivityDay (DateTime date_time)
{
DateTime = date_time;
DateTime = new DateTime (DateTime.Year, DateTime.Month, DateTime.Day);
}
}
// TODO: Move this to the repo
public class ChangeSet
{
public string UserName;
public string UserEmail;
public string Message;
@ -501,7 +488,7 @@ namespace SparkleShare {
public List <string> MovedTo;
public DateTime DateTime;
public string Hash;
public ChangeSet (string user_name, string user_email, string message, DateTime date_time, string hash)
{
@ -511,9 +498,9 @@ namespace SparkleShare {
DateTime = date_time;
Hash = hash;
Edited = new List <string> ();
Added = new List <string> ();
Deleted = new List <string> ();
Edited = new List <string> ();
Added = new List <string> ();
Deleted = new List <string> ();
MovedFrom = new List <string> ();
MovedTo = new List <string> ();

View file

@ -41,7 +41,7 @@ namespace SparkleShare {
CycleDuration = 600;
CurrentStep = 0;
Gdk.Pixbuf spinner_gallery = SparkleHelpers.GetIcon ("process-working", Size);
Gdk.Pixbuf spinner_gallery = SparkleUIHelpers.GetIcon ("process-working", Size);
int frames_in_width = spinner_gallery.Width / Size;
int frames_in_height = spinner_gallery.Height / Size;

View file

@ -37,7 +37,6 @@ namespace SparkleShare {
private Gdk.Pixbuf [] AnimationFrames;
private int FrameNumber;
private Gtk.Action FolderAction;
private double FolderSize;
@ -79,7 +78,7 @@ namespace SparkleShare {
{
Gdk.Pixbuf [] animation_frames = new Gdk.Pixbuf [5];
Gdk.Pixbuf frames_pixbuf = SparkleHelpers.GetIcon ("process-syncing-sparkleshare", 24);
Gdk.Pixbuf frames_pixbuf = SparkleUIHelpers.GetIcon ("process-syncing-sparkleshare", 24);
for (int i = 0; i < animation_frames.Length; i++)
animation_frames [i] = new Gdk.Pixbuf (frames_pixbuf, (i * 24), 0, 24, 24);
@ -133,7 +132,7 @@ namespace SparkleShare {
double size = 0;
// Ignore the temporary rebase-apply directory.
// Ignore the temporary 'rebase-apply' directory
// This prevents potential crashes when files are being
// queried whilst the files have already been deleted.
if (parent.Name.Equals ("rebase-apply"))
@ -164,25 +163,30 @@ namespace SparkleShare {
}
// Format a file size nicely.
// Format a file size nicely with small caps.
// Example: 1048576 becomes "1 ᴍʙ"
private string FormatFileSize (double byte_count)
{
string size = "";
if (byte_count >= 1099511627776)
size = String.Format (_("{0:##.##} ᴛʙ"), Math.Round (byte_count / 1099511627776, 1));
else if (byte_count >= 1073741824)
size = String.Format (_("{0:##.##} ɢʙ"), Math.Round (byte_count / 1073741824, 1));
else if (byte_count >= 1048576)
size = String.Format (_("{0:##.##} ᴍʙ"), Math.Round (byte_count / 1048576, 1));
else if (byte_count >= 1024)
size = String.Format (_("{0:##.##} ᴋʙ"), Math.Round (byte_count / 1024, 1));
else
size = byte_count.ToString () + " bytes";
return size;
return String.Format ("{0:##.##} ᴛʙ", Math.Round (byte_count / 1099511627776, 1));
else if (byte_count >= 1073741824)
return String.Format ("{0:##.##} ɢʙ", Math.Round (byte_count / 1073741824, 1));
else if (byte_count >= 1048576)
return String.Format ("{0:##.##} ᴍʙ", Math.Round (byte_count / 1048576, 1));
else if (byte_count >= 1024)
return String.Format ("{0:##.##} ᴋʙ", Math.Round (byte_count / 1024, 1));
else
return byte_count.ToString () + " bytes";
}
@ -194,20 +198,21 @@ namespace SparkleShare {
Menu = new Menu ();
// The menu item showing the status and size of the SparkleShare folder
StatusMenuItem = new MenuItem (StateText) {
Sensitive = false
};
Menu.Add (StatusMenuItem);
Menu.Add (new SeparatorMenuItem ());
FolderAction = new Gtk.Action ("", "SparkleShare") {
// A menu item that provides a link to the SparkleShare folder
Gtk.Action folder_action = new Gtk.Action ("", "SparkleShare") {
IconName = "folder-sparkleshare",
IsImportant = true
};
FolderAction.Activated += delegate {
folder_action.Activated += delegate {
Process process = new Process ();
process.StartInfo.FileName = "xdg-open";
@ -216,20 +221,22 @@ namespace SparkleShare {
};
Menu.Add (FolderAction.CreateMenuItem ());
Menu.Add (folder_action.CreateMenuItem ());
if (SparkleUI.Repositories.Count > 0) {
// Creates a menu item for each repository with a link to them
foreach (SparkleRepo repo in SparkleUI.Repositories) {
FolderAction = new Gtk.Action ("", repo.Name) {
folder_action = new Gtk.Action ("", repo.Name) {
IconName = "folder",
IsImportant = true
};
FolderAction.Activated += CreateWindowDelegate (repo.LocalPath);
folder_action.Activated += CreateWindowDelegate (repo.LocalPath);
MenuItem menu_item = (MenuItem) FolderAction.CreateMenuItem ();
MenuItem menu_item = (MenuItem) folder_action.CreateMenuItem ();
if (repo.Description != null)
menu_item.TooltipText = repo.Description;
@ -258,7 +265,6 @@ namespace SparkleShare {
};
Menu.Add (add_item);
Menu.Add (new SeparatorMenuItem ());
CheckMenuItem notify_item = new CheckMenuItem (_("Show Notifications"));
@ -296,11 +302,9 @@ namespace SparkleShare {
};
Menu.Add (about_item);
Menu.Add (new SeparatorMenuItem ());
MenuItem quit_item = new MenuItem (_("Quit"));
MenuItem quit_item = new MenuItem (_("Quit"));
quit_item.Activated += Quit;
Menu.Add (quit_item);
@ -320,9 +324,7 @@ namespace SparkleShare {
private void UpdateStatusMenuItem ()
{
Label label = (Label) StatusMenuItem.Children [0];
label.Text = StateText;
(StatusMenuItem.Children [0] as Label).Text = StateText;
Menu.ShowAll ();
}
@ -336,6 +338,7 @@ namespace SparkleShare {
}
// Shows the state and keeps the number of syncing repositories in mind
public void ShowState (bool error)
{
@ -394,7 +397,7 @@ namespace SparkleShare {
{
Timer.Stop ();
Application.Invoke (delegate { Pixbuf = SparkleHelpers.GetIcon ("sparkleshare-syncing-error", 24); });
Application.Invoke (delegate { Pixbuf = SparkleUIHelpers.GetIcon ("sparkleshare-syncing-error", 24); });
StateText = _("Failed to sync changes");
}

View file

@ -311,7 +311,7 @@ namespace SparkleShare {
if (File.Exists (notify_settings_file)) {
SparkleBubble bubble = new SparkleBubble (author, message) {
Icon = SparkleHelpers.GetAvatar (email, 32)
Icon = SparkleUIHelpers.GetAvatar (email, 32)
};
bubble.AddAction ("", "Show Events", delegate {

View file

@ -0,0 +1,126 @@
// SparkleShare, an instant update workflow to Git.
// Copyright (C) 2010 Hylke Bons <hylkebons@gmail.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 3 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 SparkleLib;
using System;
using System.IO;
using System.Net;
using System.Security.Cryptography;
using System.Text;
namespace SparkleShare {
public static class SparkleUIHelpers
{
// Creates an MD5 hash of input
public static string GetMD5 (string s)
{
MD5 md5 = new MD5CryptoServiceProvider ();
Byte[] bytes = ASCIIEncoding.Default.GetBytes (s);
Byte[] encodedBytes = md5.ComputeHash (bytes);
return BitConverter.ToString (encodedBytes).ToLower ().Replace ("-", "");
}
// Gets the avatar for a specific email address and size
public static Gdk.Pixbuf GetAvatar (string email, int size)
{
string avatar_path = SparkleHelpers.CombineMore (SparklePaths.SparkleLocalIconPath,
size + "x" + size, "status");
if (!Directory.Exists (avatar_path)) {
Directory.CreateDirectory (avatar_path);
SparkleHelpers.DebugInfo ("Config", "Created '" + avatar_path + "'");
}
string avatar_file_path = SparkleHelpers.CombineMore (avatar_path, "avatar-" + email);
if (File.Exists (avatar_file_path)) {
return new Gdk.Pixbuf (avatar_file_path);
} else {
// Let's try to get the person's gravatar for next time
WebClient WebClient = new WebClient ();
Uri uri = new Uri ("http://www.gravatar.com/avatar/" + GetMD5 (email) +
".jpg?s=" + size + "&d=404");
string tmp_file_path = SparkleHelpers.CombineMore (SparklePaths.SparkleTmpPath, email + size);
if (!File.Exists (tmp_file_path)) {
WebClient.DownloadFileAsync (uri, tmp_file_path);
WebClient.DownloadFileCompleted += delegate {
File.Delete (avatar_file_path);
FileInfo tmp_file_info = new FileInfo (tmp_file_path);
if (tmp_file_info.Length > 255)
File.Move (tmp_file_path, avatar_file_path);
};
}
// Fall back to a generic icon if there is no gravatar
if (File.Exists (avatar_file_path))
return new Gdk.Pixbuf (avatar_file_path);
else
return GetIcon ("avatar-default", size);
}
}
// Looks up an icon from the system's theme
public static Gdk.Pixbuf GetIcon (string name, int size)
{
IconTheme icon_theme = new IconTheme ();
icon_theme.AppendSearchPath (SparklePaths.SparkleIconPath);
icon_theme.AppendSearchPath (SparklePaths.SparkleLocalIconPath);
try {
return icon_theme.LoadIcon (name, size, IconLookupFlags.GenericFallback);
} catch {
try {
return icon_theme.LoadIcon ("gtk-missing-image", size, IconLookupFlags.GenericFallback);
} catch {
return null;
}
}
}
}
}