Merge with upstream (11a932b73e)

This commit is contained in:
wimh 2011-10-02 00:52:21 +02:00
parent 04b3b43f88
commit 9f729e5e3e
40 changed files with 2546 additions and 1993 deletions

1
.gitignore vendored
View file

@ -47,3 +47,4 @@ SparkleShare/Nautilus/sparkleshare-nautilus-extension.py
gnome-doc-utils.make gnome-doc-utils.make
/sparkleshare-* /sparkleshare-*
desktop.ini desktop.ini
_ReSharper.*

View file

@ -18,6 +18,7 @@
using System; using System;
using System.IO; using System.IO;
using System.Diagnostics; using System.Diagnostics;
using System.Text.RegularExpressions;
using System.Xml; using System.Xml;
namespace SparkleLib { namespace SparkleLib {
@ -25,12 +26,15 @@ namespace SparkleLib {
// Sets up a fetcher that can get remote folders // Sets up a fetcher that can get remote folders
public class SparkleFetcherGit : SparkleFetcherBase { public class SparkleFetcherGit : SparkleFetcherBase {
private SparkleGit git;
public SparkleFetcherGit (string server, string remote_folder, string target_folder) : public SparkleFetcherGit (string server, string remote_folder, string target_folder) :
base (server, remote_folder, target_folder) base (server, remote_folder, target_folder)
{ {
remote_folder = remote_folder.Trim ("/".ToCharArray ()); remote_folder = remote_folder.Trim ("/".ToCharArray ());
if (server.StartsWith("http")) { if (server.StartsWith ("http")) {
base.target_folder = target_folder; base.target_folder = target_folder;
base.remote_url = server; base.remote_url = server;
return; return;
@ -57,13 +61,20 @@ namespace SparkleLib {
} else { } else {
server = server.TrimEnd ("/".ToCharArray ()); server = server.TrimEnd ("/".ToCharArray ());
string protocol = "ssh://";
if (server.StartsWith ("ssh://")) if (server.StartsWith ("ssh://"))
server = server.Substring (6);
if (server.StartsWith ("git://")) {
server = server.Substring (6); server = server.Substring (6);
protocol = "git://";
}
if (!server.Contains ("@")) if (!server.Contains ("@"))
server = "git@" + server; server = "git@" + server;
server = "ssh://" + server; server = protocol + server;
} }
base.target_folder = target_folder; base.target_folder = target_folder;
@ -73,15 +84,51 @@ namespace SparkleLib {
public override bool Fetch () public override bool Fetch ()
{ {
SparkleGit git = new SparkleGit (SparklePaths.SparkleTmpPath, this.git = new SparkleGit (SparkleConfig.DefaultConfig.TmpPath,
"clone \"" + base.remote_url + "\" " + "\"" + base.target_folder + "\""); "clone " +
"--progress " + // Redirects progress stats to standarderror
"\"" + base.remote_url + "\" " + "\"" + base.target_folder + "\"");
this.git.StartInfo.RedirectStandardError = true;
this.git.Start ();
double percentage = 1.0;
Regex progress_regex = new Regex (@"([0-9]+)%", RegexOptions.Compiled);
while (!this.git.StandardError.EndOfStream) {
string line = this.git.StandardError.ReadLine ();
Match match = progress_regex.Match (line);
double number = 0.0;
if (match.Success) {
number = double.Parse (match.Groups [1].Value);
// The cloning progress consists of two stages: the "Compressing
// objects" stage which we count as 20% of the total progress, and
// the "Receiving objects" stage which we count as the last 80%
if (line.Contains ("|"))
// "Receiving objects" stage
number = (number / 100 * 75 + 20);
else
// "Compressing objects" stage
number = (number / 100 * 20);
}
if (number >= percentage) {
percentage = number;
// FIXME: for some reason it doesn't go above 95%
base.OnProgressChanged (percentage);
}
System.Threading.Thread.Sleep (100);
}
this.git.WaitForExit ();
git.Start (); SparkleHelpers.DebugInfo ("Git", "Exit code " + this.git.ExitCode.ToString ());
git.WaitForExit ();
SparkleHelpers.DebugInfo ("Git", "Exit code " + git.ExitCode.ToString ()); if (this.git.ExitCode != 0) {
if (git.ExitCode != 0) {
return false; return false;
} else { } else {
InstallConfiguration (); InstallConfiguration ();
@ -91,11 +138,22 @@ namespace SparkleLib {
} }
public override void Stop ()
{
if (this.git != null) {
this.git.Kill ();
this.git.Dispose ();
}
base.Stop ();
}
// Install the user's name and email and some config into // Install the user's name and email and some config into
// the newly cloned repository // the newly cloned repository
private void InstallConfiguration () private void InstallConfiguration ()
{ {
string global_config_file_path = Path.Combine (SparklePaths.SparkleConfigPath, "config.xml"); string global_config_file_path = Path.Combine (SparkleConfig.DefaultConfig.TmpPath, "config.xml");
if (!File.Exists (global_config_file_path)) if (!File.Exists (global_config_file_path))
return; return;
@ -103,17 +161,20 @@ namespace SparkleLib {
string repo_config_file_path = SparkleHelpers.CombineMore (base.target_folder, ".git", "config"); string repo_config_file_path = SparkleHelpers.CombineMore (base.target_folder, ".git", "config");
string config = String.Join (Environment.NewLine, File.ReadAllLines (repo_config_file_path)); string config = String.Join (Environment.NewLine, File.ReadAllLines (repo_config_file_path));
string n = Environment.NewLine;
// Show special characters in the logs
config = config.Replace ("[core]" + n,
"[core]" + n + "quotepath = false" + n);
// Be case sensitive explicitly to work on Mac // Be case sensitive explicitly to work on Mac
config = config.Replace ("ignorecase = true", "ignorecase = false"); config = config.Replace ("ignorecase = true", "ignorecase = false");
// Ignore permission changes // Ignore permission changes
config = config.Replace ("filemode = true", "filemode = false"); config = config.Replace ("filemode = true", "filemode = false");
config = config.Replace ("fetch = +refs/heads/*:refs/remotes/origin/*",
"fetch = +refs/heads/*:refs/remotes/origin/*" + Environment.NewLine +
"\tfetch = +refs/notes/*:refs/notes/*");
// Add user info // Add user info
string n = Environment.NewLine;
XmlDocument xml = new XmlDocument(); XmlDocument xml = new XmlDocument();
xml.Load (global_config_file_path); xml.Load (global_config_file_path);
@ -146,6 +207,10 @@ namespace SparkleLib {
// gedit and emacs // gedit and emacs
writer.WriteLine ("*~"); writer.WriteLine ("*~");
// Firefox and Chromium temporary download files
writer.WriteLine ("*.part");
writer.WriteLine ("*.crdownload");
// vi(m) // vi(m)
writer.WriteLine (".*.sw[a-z]"); writer.WriteLine (".*.sw[a-z]");
writer.WriteLine ("*.un~"); writer.WriteLine ("*.un~");
@ -168,7 +233,6 @@ namespace SparkleLib {
// Windows // Windows
writer.WriteLine ("Thumbs.db"); writer.WriteLine ("Thumbs.db");
writer.WriteLine ("Desktop.ini"); writer.WriteLine ("Desktop.ini");
writer.WriteLine ("~*");
// CVS // CVS
writer.WriteLine ("*/CVS/*"); writer.WriteLine ("*/CVS/*");

View file

@ -131,7 +131,9 @@ namespace SparkleLib {
public override bool SyncUp () public override bool SyncUp ()
{ {
Add (); Add ();
Commit ("Changes made by SparkleShare");
string message = FormatCommitMessage ();
Commit (message);
SparkleGit git = new SparkleGit (LocalPath, "push origin master"); SparkleGit git = new SparkleGit (LocalPath, "push origin master");
git.Start (); git.Start ();
@ -163,6 +165,8 @@ namespace SparkleLib {
public override bool AnyDifferences { public override bool AnyDifferences {
get { get {
FillEmptyDirectories (LocalPath);
SparkleGit git = new SparkleGit (LocalPath, "status --porcelain"); SparkleGit git = new SparkleGit (LocalPath, "status --porcelain");
git.Start (); git.Start ();
@ -197,7 +201,7 @@ namespace SparkleLib {
if (value) { if (value) {
if (!File.Exists (unsynced_file_path)) if (!File.Exists (unsynced_file_path))
File.Create (unsynced_file_path); File.Create (unsynced_file_path).Close ();
} else { } else {
File.Delete (unsynced_file_path); File.Delete (unsynced_file_path);
} }
@ -330,7 +334,7 @@ namespace SparkleLib {
// Windows doesn't allow colons in the file name, so // Windows doesn't allow colons in the file name, so
// we use "h" between the hours and minutes instead. // we use "h" between the hours and minutes instead.
string timestamp = DateTime.Now.ToString ("HH\\hmm MMM d"); string timestamp = DateTime.Now.ToString ("HH\\hmm MMM d");
string their_path = conflicting_path + " (" + SparkleConfig.DefaultConfig.UserName + ", " + timestamp + ")"; string their_path = conflicting_path + " (" + SparkleConfig.DefaultConfig.User.Name + ", " + timestamp + ")";
string abs_conflicting_path = Path.Combine (LocalPath, conflicting_path); string abs_conflicting_path = Path.Combine (LocalPath, conflicting_path);
string abs_their_path = Path.Combine (LocalPath, their_path); string abs_their_path = Path.Combine (LocalPath, their_path);
@ -452,9 +456,9 @@ namespace SparkleLib {
change_set.Folder = Name; change_set.Folder = Name;
change_set.Revision = match.Groups [1].Value; change_set.Revision = match.Groups [1].Value;
change_set.UserName = match.Groups [2].Value; change_set.User.Name = match.Groups [2].Value;
change_set.UserEmail = match.Groups [3].Value; change_set.User.Email = match.Groups [3].Value;
change_set.IsMerge = is_merge_commit; change_set.IsMagical = is_merge_commit;
change_set.Timestamp = new DateTime (int.Parse (match.Groups [4].Value), change_set.Timestamp = new DateTime (int.Parse (match.Groups [4].Value),
int.Parse (match.Groups [5].Value), int.Parse (match.Groups [6].Value), int.Parse (match.Groups [5].Value), int.Parse (match.Groups [6].Value),
@ -477,6 +481,9 @@ namespace SparkleLib {
string file_path = entry_line.Substring (39); string file_path = entry_line.Substring (39);
string to_file_path; string to_file_path;
if (file_path.EndsWith (".empty"))
file_path = file_path.Substring (0, file_path.Length - ".empty".Length);
if (change_type.Equals ("A") && !file_path.Contains (".notes")) { if (change_type.Equals ("A") && !file_path.Contains (".notes")) {
change_set.Added.Add (file_path); change_set.Added.Add (file_path);
@ -512,6 +519,22 @@ namespace SparkleLib {
} }
// Git doesn't track empty directories, so this method
// fills them all with a hidden empty file
private void FillEmptyDirectories (string path)
{
foreach (string child_path in Directory.GetDirectories (path)) {
if (child_path.EndsWith (".git") || child_path.EndsWith (".notes"))
continue;
FillEmptyDirectories (child_path);
}
if (Directory.GetFiles (path).Length == 0)
File.Create (Path.Combine (path, ".empty")).Close ();
}
// Creates a pretty commit message based on what has changed // Creates a pretty commit message based on what has changed
private string FormatCommitMessage () private string FormatCommitMessage ()
{ {

View file

@ -130,7 +130,7 @@ namespace SparkleLib {
if (value) { if (value) {
if (!File.Exists (unsynced_file_path)) if (!File.Exists (unsynced_file_path))
File.Create (unsynced_file_path); File.Create (unsynced_file_path).Close ();
} else { } else {
File.Delete (unsynced_file_path); File.Delete (unsynced_file_path);
} }
@ -234,11 +234,13 @@ namespace SparkleLib {
SparkleChangeSet change_set = new SparkleChangeSet () { SparkleChangeSet change_set = new SparkleChangeSet () {
Revision = match.Groups [9].Value, Revision = match.Groups [9].Value,
UserName = match.Groups [7].Value.Trim (), IsMagical = is_merge_commit
UserEmail = match.Groups [8].Value,
IsMerge = is_merge_commit
}; };
change_set.User.Name = match.Groups [7].Value.Trim ();
change_set.User.Email = match.Groups [8].Value;
change_set.Timestamp = new DateTime (int.Parse (match.Groups [1].Value), change_set.Timestamp = new DateTime (int.Parse (match.Groups [1].Value),
int.Parse (match.Groups [2].Value), int.Parse (match.Groups [3].Value), int.Parse (match.Groups [2].Value), int.Parse (match.Groups [3].Value),
int.Parse (match.Groups [4].Value), int.Parse (match.Groups [5].Value), 0); int.Parse (match.Groups [4].Value), int.Parse (match.Groups [5].Value), 0);

View file

@ -11,10 +11,6 @@ SOURCES = \
Defines.cs \ Defines.cs \
Git/SparkleFetcherGit.cs \ Git/SparkleFetcherGit.cs \
Git/SparkleRepoGit.cs \ Git/SparkleRepoGit.cs \
Hg/SparkleFetcherHg.cs \
Hg/SparkleRepoHg.cs \
Scp/SparkleFetcherScp.cs \
Scp/SparkleRepoScp.cs \
SparkleBackend.cs \ SparkleBackend.cs \
SparkleChangeSet.cs \ SparkleChangeSet.cs \
SparkleConfig.cs \ SparkleConfig.cs \
@ -24,7 +20,6 @@ SOURCES = \
SparkleListenerIrc.cs \ SparkleListenerIrc.cs \
SparkleListenerTcp.cs \ SparkleListenerTcp.cs \
SparkleOptions.cs \ SparkleOptions.cs \
SparklePaths.cs \
SparkleRepoBase.cs \ SparkleRepoBase.cs \
SparkleWatcher.cs SparkleWatcher.cs

View file

@ -1,139 +0,0 @@
// SparkleShare, a collaboration and sharing tool.
// 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 System;
using System.IO;
using System.Diagnostics;
using System.Xml;
namespace SparkleLib {
// Sets up a fetcher that can get remote folders
public class SparkleFetcherScp : SparkleFetcherBase {
public SparkleFetcherScp (string server, string remote_folder, string target_folder) :
base (server, remote_folder, target_folder) { }
public override bool Fetch ()
{
SparkleScp scp = new SparkleScp (SparklePaths.SparkleTmpPath,
"-r \"" + base.remote_url + "\" " + "\"" + base.target_folder + "\"");
scp.Start ();
scp.WaitForExit ();
SparkleHelpers.DebugInfo ("Scp", "Exit code " + scp.ExitCode.ToString ());
if (scp.ExitCode != 0) {
return false;
} else {
InstallConfiguration ();
InstallExcludeRules ();
return true;
}
}
// Install the user's name and email and some config into
// the newly cloned repository
private void InstallConfiguration ()
{
string log_file_path = SparkleHelpers.CombineMore (base.target_folder, ".sparkleshare", "log");
File.Create (log_file_path);
string config_file_path = SparkleHelpers.CombineMore (base.target_folder, ".sparkleshare", "config");
File.Create (config_file_path);
string config = "";
// Write the config to the file
TextWriter writer = new StreamWriter (config_file_path);
writer.WriteLine (config);
writer.Close ();
SparkleHelpers.DebugInfo ("Config", "Added configuration to '" + config_file_path + "'");
}
// Add a .gitignore file to the repo
private void InstallExcludeRules ()
{
string exlude_rules_file_path = SparkleHelpers.CombineMore (base.target_folder, ".sparkleshare", "exclude");
File.Create (exlude_rules_file_path);
TextWriter writer = new StreamWriter (exlude_rules_file_path);
// gedit and emacs
writer.WriteLine ("*~");
// vi(m)
writer.WriteLine (".*.sw[a-z]");
writer.WriteLine ("*.un~");
writer.WriteLine ("*.swp");
writer.WriteLine ("*.swo");
// KDE
writer.WriteLine (".directory");
// Mac OSX
writer.WriteLine (".DS_Store");
writer.WriteLine ("Icon?");
writer.WriteLine ("._*");
writer.WriteLine (".Spotlight-V100");
writer.WriteLine (".Trashes");
// Mac OSX
writer.WriteLine ("*(Autosaved).graffle");
// Windows
writer.WriteLine ("Thumbs.db");
writer.WriteLine ("Desktop.ini");
// CVS
writer.WriteLine ("*/CVS/*");
writer.WriteLine (".cvsignore");
writer.WriteLine ("*/.cvsignore");
// Subversion
writer.WriteLine ("/.svn/*");
writer.WriteLine ("*/.svn/*");
writer.Close ();
}
}
public class SparkleScp : Process {
public SparkleScp (string path, string args) : base ()
{
EnableRaisingEvents = true;
StartInfo.FileName = SparkleBackend.DefaultBackend.Path;
StartInfo.Arguments = args;
StartInfo.RedirectStandardOutput = true;
StartInfo.UseShellExecute = false;
StartInfo.WorkingDirectory = path;
}
new public void Start ()
{
SparkleHelpers.DebugInfo ("Cmd", StartInfo.FileName + " " + StartInfo.Arguments);
base.Start ();
}
}
}

View file

@ -1,115 +0,0 @@
// SparkleShare, a collaboration and sharing tool.
// 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 System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text.RegularExpressions;
namespace SparkleLib {
public class SparkleRepoScp : SparkleRepoBase {
public SparkleRepoScp (string path, SparkleBackend backend) :
base (path, backend) { }
public override string Identifier {
get {
return "sparkles";
}
}
public override string CurrentRevision {
get {
return "";
}
}
public override bool CheckForRemoteChanges ()
{
return true;
}
public override bool SyncUp ()
{
return true;
}
public override bool SyncDown ()
{
return true;
}
public override bool AnyDifferences {
get {
return false;
}
}
public override bool HasUnsyncedChanges {
get {
string unsynced_file_path = SparkleHelpers.CombineMore (LocalPath,
".sparkleshare", "has_unsynced_changes");
return File.Exists (unsynced_file_path);
}
set {
string unsynced_file_path = SparkleHelpers.CombineMore (LocalPath,
".sparkleshare", "has_unsynced_changes");
if (value) {
if (!File.Exists (unsynced_file_path))
File.Create (unsynced_file_path);
} else {
File.Delete (unsynced_file_path);
}
}
}
public override List <SparkleChangeSet> GetChangeSets (int count)
{
var l = new List<SparkleChangeSet> ();
l.Add (new SparkleChangeSet () { UserName = "test", UserEmail = "test", Revision = "test", Timestamp = DateTime.Now });
return l;
}
public override void CreateInitialChangeSet ()
{
base.CreateInitialChangeSet ();
}
public override bool UsesNotificationCenter
{
get {
string file_path = SparkleHelpers.CombineMore (LocalPath, ".sparkleshare", "disable_notification_center");
return !File.Exists (file_path);
}
}
}
}

View file

@ -32,7 +32,7 @@ namespace SparkleLib {
public SparkleBackend (string name, string [] paths) public SparkleBackend (string name, string [] paths)
{ {
Name = name; Name = name;
Path = "git"; // default Path = "git";
foreach (string path in paths) { foreach (string path in paths) {
if (File.Exists (path)) { if (File.Exists (path)) {

View file

@ -16,20 +16,20 @@
using System; using System;
using System.IO;
using System.Collections.Generic; using System.Collections.Generic;
namespace SparkleLib { namespace SparkleLib {
public class SparkleChangeSet { public class SparkleChangeSet {
public string UserName; public SparkleUser User = new SparkleUser ("Unknown", "Unknown");
public string UserEmail;
public string Folder; public string Folder;
public string Revision; public string Revision;
public DateTime Timestamp; public DateTime Timestamp;
public DateTime FirstTimestamp; public DateTime FirstTimestamp;
public bool IsMerge = false; public bool IsMagical = false;
public List<string> Added = new List<string> (); public List<string> Added = new List<string> ();
public List<string> Deleted = new List<string> (); public List<string> Deleted = new List<string> ();
@ -76,10 +76,44 @@ namespace SparkleLib {
public class SparkleNote { public class SparkleNote {
public string UserName; public SparkleUser User;
public string UserEmail;
public DateTime Timestamp; public DateTime Timestamp;
public string Body; public string Body;
} }
public class SparkleUser {
public string Name;
public string Email;
public string PublicKey;
public SparkleUser (string name, string email)
{
Name = name;
Email = email;
}
}
public class SparkleFolder {
public string Name;
// TODO: Uri
public string FullPath {
get {
return Path.Combine (SparkleConfig.DefaultConfig.FoldersPath, Name);
}
}
public SparkleFolder (string name)
{
Name = name;
}
}
} }

View file

@ -23,19 +23,37 @@ using System.Xml;
#if __MonoCS__ #if __MonoCS__
using Mono.Unix; using Mono.Unix;
#endif #endif
namespace SparkleLib { namespace SparkleLib {
public class SparkleConfig : XmlDocument { public class SparkleConfig : XmlDocument {
public static SparkleConfig DefaultConfig = new SparkleConfig ( public static string ConfigPath = Path.Combine (
SparklePaths.SparkleConfigPath, "config.xml"); Environment.GetFolderPath (Environment.SpecialFolder.ApplicationData),
"sparkleshare");
public string Path; public static SparkleConfig DefaultConfig = new SparkleConfig (ConfigPath, "config.xml");
public string FullPath;
public string HomePath = Environment.GetFolderPath (Environment.SpecialFolder.Personal);
public string TmpPath;
public string FoldersPath {
get {
if (GetConfigOption ("folders_path") != null)
return GetConfigOption ("folders_path");
else
return Path.Combine (HomePath, "SparkleShare");
}
}
public SparkleConfig (string config_path, string config_file_name) public SparkleConfig (string config_path, string config_file_name)
{ {
Path = System.IO.Path.Combine (config_path, config_file_name); FullPath = System.IO.Path.Combine (config_path, config_file_name);
TmpPath = Path.Combine (FoldersPath, ".tmp");
if (!Directory.Exists (config_path)) { if (!Directory.Exists (config_path)) {
Directory.CreateDirectory (config_path); Directory.CreateDirectory (config_path);
@ -48,10 +66,30 @@ namespace SparkleLib {
SparkleHelpers.DebugInfo ("Config", "Created \"" + icons_path + "\""); SparkleHelpers.DebugInfo ("Config", "Created \"" + icons_path + "\"");
} }
if (!File.Exists (Path)) try {
Load (FullPath);
} catch (TypeInitializationException) {
CreateInitialConfig (); CreateInitialConfig ();
Load (Path); } catch (IOException) {
CreateInitialConfig ();
} catch (XmlException) {
FileInfo file = new FileInfo (FullPath);
if (file.Length == 0) {
File.Delete (FullPath);
CreateInitialConfig ();
} else {
throw new XmlException (FullPath + " does not contain a valid config XML structure.");
}
} finally {
Load (FullPath);
}
} }
@ -59,20 +97,23 @@ namespace SparkleLib {
{ {
string user_name = "Unknown"; string user_name = "Unknown";
if (SparkleBackend.Platform == PlatformID.Unix ||
SparkleBackend.Platform == PlatformID.MacOSX) {
#if __MonoCS__ #if __MonoCS__
user_name = new UnixUserInfo (UnixEnvironment.UserName).RealName; user_name = new UnixUserInfo (UnixEnvironment.UserName).RealName;
if (string.IsNullOrEmpty (user_name)) if (string.IsNullOrEmpty (user_name))
user_name = UnixEnvironment.UserName; user_name = UnixEnvironment.UserName;
else else
user_name = user_name.TrimEnd (",".ToCharArray()); user_name = user_name.TrimEnd (",".ToCharArray());
#else
user_name = Environment.UserName;
#endif #endif
} else {
user_name = Environment.UserName;
}
if (string.IsNullOrEmpty (user_name)) if (string.IsNullOrEmpty (user_name))
user_name = "Unknown"; user_name = "Unknown";
TextWriter writer = new StreamWriter (Path); TextWriter writer = new StreamWriter (FullPath);
string n = Environment.NewLine; string n = Environment.NewLine;
writer.Write ("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" + n + writer.Write ("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" + n +
@ -84,36 +125,31 @@ namespace SparkleLib {
"</sparkleshare>"); "</sparkleshare>");
writer.Close (); writer.Close ();
SparkleHelpers.DebugInfo ("Config", "Created \"" + Path + "\""); SparkleHelpers.DebugInfo ("Config", "Created \"" + FullPath + "\"");
} }
public string UserName { public SparkleUser User {
get { get {
XmlNode node = SelectSingleNode ("/sparkleshare/user/name/text()"); XmlNode name_node = SelectSingleNode ("/sparkleshare/user/name/text()");
return node.Value; string name = name_node.Value;
XmlNode email_node = SelectSingleNode ("/sparkleshare/user/email/text()");
string email = email_node.Value;
return new SparkleUser (name, email);
} }
set { set {
XmlNode node = SelectSingleNode ("/sparkleshare/user/name/text()"); SparkleUser user = (SparkleUser) value;
node.InnerText = value;
Save (); XmlNode name_node = SelectSingleNode ("/sparkleshare/user/name/text()");
} name_node.InnerText = user.Name;
}
XmlNode email_node = SelectSingleNode ("/sparkleshare/user/email/text()");
email_node.InnerText = user.Email;
public string UserEmail { this.Save ();
get {
XmlNode node = SelectSingleNode ("/sparkleshare/user/email/text()");
return node.Value;
}
set {
XmlNode node = SelectSingleNode ("/sparkleshare/user/email/text()");
node.InnerText = value;
Save ();
} }
} }
@ -149,22 +185,7 @@ namespace SparkleLib {
XmlNode node_root = SelectSingleNode ("/sparkleshare"); XmlNode node_root = SelectSingleNode ("/sparkleshare");
node_root.AppendChild (node_folder); node_root.AppendChild (node_folder);
Save (); this.Save ();
}
public bool SetFolderOptionalAttribute (string name, string key, string value)
{
XmlNode folder = this.GetFolder(name);
if (folder == null) return false;
if (folder[key] != null) {
folder[key].InnerText = value;
} else {
XmlNode new_node = CreateElement(key);
new_node.InnerText = value;
folder.AppendChild(new_node);
}
return true;
} }
@ -175,28 +196,64 @@ namespace SparkleLib {
SelectSingleNode ("/sparkleshare").RemoveChild (node_folder); SelectSingleNode ("/sparkleshare").RemoveChild (node_folder);
} }
Save (); this.Save ();
} }
public bool FolderExists (string name) public bool FolderExists (string name)
{ {
XmlNode folder = this.GetFolder(name); XmlNode folder = this.GetFolder (name);
return folder != null; return (folder != null);
} }
public string GetBackendForFolder (string name) public string GetBackendForFolder (string name)
{ {
return this.GetFolderValue(name, "backend"); return this.GetFolderValue (name, "backend");
} }
public string GetUrlForFolder (string name) public string GetUrlForFolder (string name)
{ {
return this.GetFolderValue(name, "url"); return this.GetFolderValue (name, "url");
} }
public bool SetFolderOptionalAttribute (string folder_name, string key, string value)
{
XmlNode folder = this.GetFolder (folder_name);
if (folder == null)
return false;
if (folder [key] != null) {
folder [key].InnerText = value;
} else {
XmlNode new_node = CreateElement (key);
new_node.InnerText = value;
folder.AppendChild (new_node);
}
return true;
}
public string GetFolderOptionalAttribute (string folder_name, string key)
{
XmlNode folder = this.GetFolder (folder_name);
if (folder != null) {
if (folder [key] != null)
return folder [key].InnerText;
else
return null;
} else {
return null;
}
}
public List<string> Hosts { public List<string> Hosts {
get { get {
@ -204,6 +261,7 @@ namespace SparkleLib {
foreach (XmlNode node_folder in SelectNodes ("/sparkleshare/folder")) { foreach (XmlNode node_folder in SelectNodes ("/sparkleshare/folder")) {
Uri uri = new Uri (node_folder ["url"].InnerText); Uri uri = new Uri (node_folder ["url"].InnerText);
if (!hosts.Contains (uri.Host)) if (!hosts.Contains (uri.Host))
hosts.Add (uri.Host); hosts.Add (uri.Host);
} }
@ -213,21 +271,40 @@ namespace SparkleLib {
} }
public string GetAnnouncementsForFolder (string name) public List<string> HostsWithUsername {
{ get {
return this.GetFolderValue(name, "announcements"); List<string> hosts = new List<string> ();
foreach (XmlNode node_folder in SelectNodes ("/sparkleshare/folder")) {
Uri uri = new Uri (node_folder ["url"].InnerText);
if ("git" != uri.UserInfo && !hosts.Contains (uri.UserInfo + "@" + uri.Host))
hosts.Add (uri.UserInfo + "@" + uri.Host);
}
return hosts;
}
} }
public string GetAnnouncementUrlForFolder (string name) private XmlNode GetFolder (string name)
{ {
// examples? return SelectSingleNode (String.Format("/sparkleshare/folder[name='{0}']", name));
// tcp://localhost:9999/
// xmpp:someuser@somexmppserver?canhavefunnybits
// irc://hbons/#somechatroom
return this.GetFolderValue(name, "announcements_url");
} }
private string GetFolderValue (string name, string key)
{
XmlNode folder = this.GetFolder(name);
if ((folder != null) && (folder [key] != null)) {
return folder [key].InnerText;
}
return null;
}
public string GetConfigOption (string name) public string GetConfigOption (string name)
{ {
XmlNode node = SelectSingleNode ("/sparkleshare/" + name); XmlNode node = SelectSingleNode ("/sparkleshare/" + name);
@ -255,34 +332,17 @@ namespace SparkleLib {
} }
SparkleHelpers.DebugInfo ("Config", "Updated " + name + ":" + content); SparkleHelpers.DebugInfo ("Config", "Updated " + name + ":" + content);
Save (); this.Save ();
} }
public void Save () private void Save ()
{ {
if (!File.Exists (Path)) if (!File.Exists (FullPath))
throw new ConfigFileNotFoundException (Path + " does not exist"); throw new ConfigFileNotFoundException (FullPath + " does not exist");
Save (Path); this.Save (FullPath);
SparkleHelpers.DebugInfo ("Config", "Updated \"" + Path + "\""); SparkleHelpers.DebugInfo ("Config", "Updated \"" + FullPath + "\"");
}
private XmlNode GetFolder (string name)
{
return SelectSingleNode(String.Format("/sparkleshare/folder[name='{0}']", name));
}
private string GetFolderValue (string name, string key)
{
XmlNode folder = this.GetFolder(name);
if ((folder != null) && (folder[key] != null)) {
return folder[key].InnerText;
}
return null;
} }
} }
@ -293,3 +353,4 @@ namespace SparkleLib {
base (message) { } base (message) { }
} }
} }

View file

@ -33,18 +33,19 @@ namespace SparkleLib {
public delegate void StartedEventHandler (); public delegate void StartedEventHandler ();
public delegate void FinishedEventHandler (); public delegate void FinishedEventHandler ();
public delegate void FailedEventHandler (); public delegate void FailedEventHandler ();
public delegate void ProgressChangedEventHandler (double percentage);
public event StartedEventHandler Started; public event StartedEventHandler Started;
public event FinishedEventHandler Finished; public event FinishedEventHandler Finished;
public event FailedEventHandler Failed; public event FailedEventHandler Failed;
public event ProgressChangedEventHandler ProgressChanged;
protected string target_folder; protected string target_folder;
protected string remote_url; protected string remote_url;
private Thread thread; private Thread thread;
public abstract bool Fetch ();
public SparkleFetcherBase (string server, string remote_folder, string target_folder) public SparkleFetcherBase (string server, string remote_folder, string target_folder)
{ {
this.target_folder = target_folder; this.target_folder = target_folder;
@ -52,6 +53,9 @@ namespace SparkleLib {
} }
public abstract bool Fetch ();
// Clones the remote repository // Clones the remote repository
public void Start () public void Start ()
{ {
@ -97,6 +101,13 @@ namespace SparkleLib {
} }
public virtual void Stop ()
{
this.thread.Abort ();
this.thread.Join ();
}
public string RemoteUrl { public string RemoteUrl {
get { get {
return this.remote_url; return this.remote_url;
@ -112,10 +123,16 @@ namespace SparkleLib {
} }
} }
protected void OnProgressChanged (double percentage) {
if (ProgressChanged != null)
ProgressChanged (percentage);
}
private void DisableHostKeyCheckingForHost (string host) private void DisableHostKeyCheckingForHost (string host)
{ {
string path = SparklePaths.HomePath; string path = SparkleConfig.DefaultConfig.HomePath;
if (!(SparkleBackend.Platform == PlatformID.Unix || if (!(SparkleBackend.Platform == PlatformID.Unix ||
SparkleBackend.Platform == PlatformID.MacOSX)) { SparkleBackend.Platform == PlatformID.MacOSX)) {
@ -154,7 +171,7 @@ namespace SparkleLib {
private void EnableHostKeyCheckingForHost (string host) private void EnableHostKeyCheckingForHost (string host)
{ {
string path = SparklePaths.HomePath; string path = SparkleConfig.DefaultConfig.HomePath;
if (!(SparkleBackend.Platform == PlatformID.Unix || if (!(SparkleBackend.Platform == PlatformID.Unix ||
SparkleBackend.Platform == PlatformID.MacOSX)) { SparkleBackend.Platform == PlatformID.MacOSX)) {

View file

@ -41,35 +41,44 @@ namespace SparkleLib {
public static SparkleListenerBase CreateListener (string folder_name, string folder_identifier) public static SparkleListenerBase CreateListener (string folder_name, string folder_identifier)
{ {
string announce_uri = SparkleConfig.DefaultConfig.GetAnnouncementUrlForFolder (folder_name); string uri = SparkleConfig.DefaultConfig.GetFolderOptionalAttribute (
folder_name, "announcements_url");
if (announce_uri == null) { if (uri == null) {
// This is SparkleShare's centralized notification service. // This is SparkleShare's centralized notification service.
// Don't worry, we only use this server as a backup if you // Don't worry, we only use this server as a backup if you
// don't have your own. All data needed to connect is hashed and // don't have your own. All data needed to connect is hashed and
// we don't store any personal information ever // we don't store any personal information ever
announce_uri = "irc://204.62.14.135/"; uri = "tcp://204.62.14.135:1986"; // TODO: announcements.sparkleshare.org
} }
Uri announce_uri = new Uri (uri);
// We use only one listener per server to keep
// the number of connections as low as possible
foreach (SparkleListenerBase listener in listeners) { foreach (SparkleListenerBase listener in listeners) {
if (listener.Server.Equals (announce_uri)) { if (listener.Server.Equals (announce_uri)) {
SparkleHelpers.DebugInfo ("ListenerFactory", "Refered to existing listener for " + announce_uri); SparkleHelpers.DebugInfo ("ListenerFactory",
"Refered to existing listener for " + announce_uri);
listener.AlsoListenTo (folder_identifier); listener.AlsoListenTo (folder_identifier);
return (SparkleListenerBase) listener; return (SparkleListenerBase) listener;
} }
} }
Uri listen_on = new Uri (announce_uri); // Create a new listener with the appropriate
// type if one doesn't exist yet for that server
switch (listen_on.Scheme) { switch (announce_uri.Scheme) {
case "tcp": case "tcp":
listeners.Add (new SparkleListenerTcp (listen_on, folder_identifier)); listeners.Add (new SparkleListenerTcp (announce_uri, folder_identifier));
break; break;
case "irc": case "irc":
default: listeners.Add (new SparkleListenerIrc (announce_uri, folder_identifier));
listeners.Add (new SparkleListenerIrc (listen_on, folder_identifier)); break;
break; default:
listeners.Add (new SparkleListenerTcp (announce_uri, folder_identifier));
break;
} }
SparkleHelpers.DebugInfo ("ListenerFactory", "Issued new listener for " + announce_uri); SparkleHelpers.DebugInfo ("ListenerFactory", "Issued new listener for " + announce_uri);
@ -109,20 +118,25 @@ namespace SparkleLib {
protected Uri server; protected Uri server;
protected Timer reconnect_timer = new Timer { Interval = 60 * 1000, Enabled = true }; protected Timer reconnect_timer = new Timer { Interval = 60 * 1000, Enabled = true };
public SparkleListenerBase (Uri server, string folder_identifier) { public SparkleListenerBase (Uri server, string folder_identifier)
{
this.server = server;
this.reconnect_timer.Elapsed += delegate { this.reconnect_timer.Elapsed += delegate {
if (!IsConnected && !this.is_connecting) if (!IsConnected && !this.is_connecting)
Reconnect (); Reconnect ();
}; };
this.server = server;
this.reconnect_timer.Start (); this.reconnect_timer.Start ();
} }
public void AnnounceBase (SparkleAnnouncement announcement) { public void AnnounceBase (SparkleAnnouncement announcement)
{
if (IsConnected) { if (IsConnected) {
SparkleHelpers.DebugInfo ("Listener", "Announcing to " + announcement.FolderIdentifier + " on " + this.server); SparkleHelpers.DebugInfo ("Listener",
"Announcing to " + announcement.FolderIdentifier + " on " + this.server);
Announce (announcement); Announce (announcement);
} else { } else {
@ -161,6 +175,7 @@ namespace SparkleLib {
if (this.queue_up.Count > 0) { if (this.queue_up.Count > 0) {
SparkleHelpers.DebugInfo ("Listener", "Delivering queued messages..."); SparkleHelpers.DebugInfo ("Listener", "Delivering queued messages...");
foreach (SparkleAnnouncement announcement in this.queue_up) { foreach (SparkleAnnouncement announcement in this.queue_up) {
AnnounceBase (announcement); AnnounceBase (announcement);
this.queue_up.Remove (announcement); this.queue_up.Remove (announcement);
@ -171,7 +186,7 @@ namespace SparkleLib {
public void OnDisconnected () public void OnDisconnected ()
{ {
SparkleHelpers.DebugInfo ("Listener", "Disonnected"); SparkleHelpers.DebugInfo ("Listener", "Disonnected from " + Server);
if (Disconnected != null) if (Disconnected != null)
Disconnected (); Disconnected ();

View file

@ -48,6 +48,20 @@ namespace SparkleLib {
PingInterval = 60 PingInterval = 60
}; };
string proxy = Environment.GetEnvironmentVariable ("http_proxy");
Uri proxy_uri = null;
if (!String.IsNullOrEmpty (proxy) &&
Uri.TryCreate (proxy, UriKind.Absolute, out proxy_uri)) {
#if __MonoCS__
if (proxy_uri.Scheme == "http") {
this.client.ProxyType = ProxyType.Http;
this.client.ProxyHost = proxy_uri.Host;
this.client.ProxyPort = proxy_uri.Port;
}
#endif
}
this.client.OnConnected += delegate { this.client.OnConnected += delegate {
base.is_connecting = false; base.is_connecting = false;
OnConnected (); OnConnected ();
@ -92,11 +106,12 @@ namespace SparkleLib {
int port = base.server.Port; int port = base.server.Port;
if (port < 0) port = 6667; if (port < 0) port = 6667;
this.client.Connect (base.server.Host, port); this.client.Connect (base.server.Host, port);
this.client.Login (this.nick, this.nick); this.client.Login (this.nick, this.nick, 8, this.nick);
foreach (string channel in base.channels) { foreach (string channel in base.channels) {
SparkleHelpers.DebugInfo ("ListenerIrc", "Joining channel " + channel); SparkleHelpers.DebugInfo ("ListenerIrc", "Joining channel " + channel);
this.client.RfcJoin (channel); this.client.RfcJoin (channel);
this.client.RfcMode (channel, "+s");
} }
// List to the channel, this blocks the thread // List to the channel, this blocks the thread
@ -124,6 +139,7 @@ namespace SparkleLib {
if (IsConnected) { if (IsConnected) {
SparkleHelpers.DebugInfo ("ListenerIrc", "Joining channel " + channel); SparkleHelpers.DebugInfo ("ListenerIrc", "Joining channel " + channel);
this.client.RfcJoin (channel); this.client.RfcJoin (channel);
this.client.RfcMode (channel, "+s");
} }
} }
} }

View file

@ -46,11 +46,12 @@ namespace SparkleLib {
public override bool IsConnected { public override bool IsConnected {
get { get {
//return this.client.IsConnected;
bool result = false; bool result = false;
lock (this.mutex) { lock (this.mutex) {
result = this.connected; result = this.connected;
} }
return result; return result;
} }
} }
@ -70,40 +71,46 @@ namespace SparkleLib {
int port = Server.Port; int port = Server.Port;
if (port < 0) port = 9999; if (port < 0) port = 9999;
this.socket.Connect (Server.Host, port); this.socket.Connect (Server.Host, port);
lock (this.mutex) { lock (this.mutex) {
base.is_connecting = false; base.is_connecting = false;
this.connected = true; this.connected = true;
OnConnected ();
foreach (string channel in base.channels) { foreach (string channel in base.channels) {
SparkleHelpers.DebugInfo ("ListenerTcp", "Subscribing to channel " + channel); SparkleHelpers.DebugInfo ("ListenerTcp", "Subscribing to channel " + channel);
this.socket.Send (Encoding.UTF8.GetBytes ("subscribe " + channel + "\n")); this.socket.Send (Encoding.UTF8.GetBytes ("subscribe " + channel + "\n"));
} }
} }
byte [] bytes = new byte [4096]; byte [] bytes = new byte [4096];
// List to the channels, this blocks the thread // List to the channels, this blocks the thread
while (this.socket.Connected) { while (this.socket.Connected) {
int bytes_read = this.socket.Receive (bytes); int bytes_read = this.socket.Receive (bytes);
if (bytes_read > 0) { if (bytes_read > 0) {
string received = Encoding.UTF8.GetString (bytes); string received = Encoding.UTF8.GetString (bytes);
string folder_identifier = received.Substring (0, received.IndexOf ("!")); string folder_identifier = received.Substring (0, received.IndexOf ("!"));
string message = received.Substring (received.IndexOf ("!") + 1); string message = received.Substring (received.IndexOf ("!") + 1);
OnAnnouncement (new SparkleAnnouncement (folder_identifier, message)); OnAnnouncement (new SparkleAnnouncement (folder_identifier, message));
} else { } else {
SparkleHelpers.DebugInfo ("ListenerTcp", "Error on socket"); SparkleHelpers.DebugInfo ("ListenerTcp", "Error on socket");
lock (this.mutex) { lock (this.mutex) {
this.socket.Close(); this.socket.Close ();
this.connected = false; this.connected = false;
OnDisconnected ();
} }
} }
} }
SparkleHelpers.DebugInfo ("ListenerTcp", "Disconnected from " + Server.Host); SparkleHelpers.DebugInfo ("ListenerTcp", "Disconnected from " + Server.Host);
// TODO: attempt to reconnect..?
} catch (SocketException e) { } catch (SocketException e) {
SparkleHelpers.DebugInfo ("ListenerTcp", "Could not connect to " + Server + ": " + e.Message); SparkleHelpers.DebugInfo ("ListenerTcp", "Could not connect to " + Server + ": " + e.Message);
} }

View file

@ -67,9 +67,12 @@ namespace SparkleLib {
public delegate void SyncStatusChangedEventHandler (SyncStatus new_status); public delegate void SyncStatusChangedEventHandler (SyncStatus new_status);
public event SyncStatusChangedEventHandler SyncStatusChanged; public event SyncStatusChangedEventHandler SyncStatusChanged;
public delegate void NewChangeSetEventHandler (SparkleChangeSet change_set, string source_path); public delegate void NewChangeSetEventHandler (SparkleChangeSet change_set);
public event NewChangeSetEventHandler NewChangeSet; public event NewChangeSetEventHandler NewChangeSet;
public delegate void NewNoteEventHandler (string user_name, string user_email);
public event NewNoteEventHandler NewNote;
public delegate void ConflictResolvedEventHandler (); public delegate void ConflictResolvedEventHandler ();
public event ConflictResolvedEventHandler ConflictResolved; public event ConflictResolvedEventHandler ConflictResolved;
@ -253,6 +256,8 @@ namespace SparkleLib {
this.listener.Announcement += delegate (SparkleAnnouncement announcement) { this.listener.Announcement += delegate (SparkleAnnouncement announcement) {
string identifier = Identifier; string identifier = Identifier;
Console.WriteLine (announcement.Message + " ! " + CurrentRevision);
if (announcement.FolderIdentifier == identifier && if (announcement.FolderIdentifier == identifier &&
!announcement.Message.Equals (CurrentRevision)) { !announcement.Message.Equals (CurrentRevision)) {
if ((Status != SyncStatus.SyncUp) && if ((Status != SyncStatus.SyncUp) &&
@ -276,7 +281,6 @@ namespace SparkleLib {
{ {
lock (this.change_lock) { lock (this.change_lock) {
if (this.has_changed) { if (this.has_changed) {
Console.WriteLine ("checking...");
if (this.sizebuffer.Count >= 4) if (this.sizebuffer.Count >= 4)
this.sizebuffer.RemoveAt (0); this.sizebuffer.RemoveAt (0);
@ -363,8 +367,8 @@ namespace SparkleLib {
if (match_notes.Success) { if (match_notes.Success) {
SparkleNote note = new SparkleNote () { SparkleNote note = new SparkleNote () {
UserName = match_notes.Groups [1].Value, User = new SparkleUser (match_notes.Groups [1].Value,
UserEmail = match_notes.Groups [2].Value, match_notes.Groups [2].Value),
Timestamp = new DateTime (1970, 1, 1).AddSeconds (int.Parse (match_notes.Groups [3].Value)), Timestamp = new DateTime (1970, 1, 1).AddSeconds (int.Parse (match_notes.Groups [3].Value)),
Body = match_notes.Groups [4].Value Body = match_notes.Groups [4].Value
}; };
@ -446,13 +450,26 @@ namespace SparkleLib {
if (change_sets != null && change_sets.Count > 0) { if (change_sets != null && change_sets.Count > 0) {
SparkleChangeSet change_set = change_sets [0]; SparkleChangeSet change_set = change_sets [0];
if (NewChangeSet != null) bool note_added = false;
NewChangeSet (change_set, LocalPath); foreach (string added in change_set.Added) {
if (added.Contains (".notes")) {
if (NewNote != null)
NewNote (change_set.User.Name, change_set.User.Email);
note_added = true;
break;
}
}
if (!note_added) {
if (NewChangeSet != null)
NewChangeSet (change_set);
}
} }
// There could be changes from a // There could be changes from a resolved
// resolved conflict. Tries only once, // conflict. Tries only once, then lets
//then let the timer try again periodicallly // the timer try again periodically
if (HasUnsyncedChanges) if (HasUnsyncedChanges)
SyncUp (); SyncUp ();
@ -510,8 +527,8 @@ namespace SparkleLib {
string n = Environment.NewLine; string n = Environment.NewLine;
note = "<note>" + n + note = "<note>" + n +
" <user>" + n + " <user>" + n +
" <name>" + SparkleConfig.DefaultConfig.UserName + "</name>" + n + " <name>" + SparkleConfig.DefaultConfig.User.Name + "</name>" + n +
" <email>" + SparkleConfig.DefaultConfig.UserEmail + "</email>" + n + " <email>" + SparkleConfig.DefaultConfig.User.Email + "</email>" + n +
" </user>" + n + " </user>" + n +
" <timestamp>" + timestamp + "</timestamp>" + n + " <timestamp>" + timestamp + "</timestamp>" + n +
" <body>" + note + "</body>" + n + " <body>" + note + "</body>" + n +

View file

@ -79,16 +79,12 @@
<Compile Include="..\Hg\SparkleRepoHg.cs"> <Compile Include="..\Hg\SparkleRepoHg.cs">
<Link>SparkleRepoHg.cs</Link> <Link>SparkleRepoHg.cs</Link>
</Compile> </Compile>
<Compile Include="..\Scp\SparkleFetcherScp.cs">
<Link>SparkleFetcherScp.cs</Link>
<SubType>Component</SubType>
</Compile>
<Compile Include="..\Scp\SparkleRepoScp.cs">
<Link>SparkleRepoScp.cs</Link>
</Compile>
<Compile Include="..\SparkleConfig.cs"> <Compile Include="..\SparkleConfig.cs">
<Link>SparkleConfig.cs</Link> <Link>SparkleConfig.cs</Link>
</Compile> </Compile>
<Compile Include="..\SparklePaths.cs">
<Link>SparklePaths.cs</Link>
</Compile>
<Compile Include="..\SparkleRepoBase.cs"> <Compile Include="..\SparkleRepoBase.cs">
<Link>SparkleRepoBase.cs</Link> <Link>SparkleRepoBase.cs</Link>
</Compile> </Compile>
@ -105,7 +101,6 @@
</Compile> </Compile>
<Compile Include="..\SparkleFetcherBase.cs" /> <Compile Include="..\SparkleFetcherBase.cs" />
<Compile Include="..\SparkleHelpers.cs" /> <Compile Include="..\SparkleHelpers.cs" />
<Compile Include="..\SparklePaths.cs" />
<Compile Include="..\SparkleOptions.cs" /> <Compile Include="..\SparkleOptions.cs" />
<Compile Include="..\SparkleChangeSet.cs" /> <Compile Include="..\SparkleChangeSet.cs" />
<Compile Include="..\SparkleListenerBase.cs" /> <Compile Include="..\SparkleListenerBase.cs" />

View file

@ -12,19 +12,20 @@ BUILD_DEFINES="-define:HAVE_APP_INDICATOR"
endif endif
SOURCES = \ SOURCES = \
Program.cs \
SparkleAbout.cs \ SparkleAbout.cs \
SparkleAboutController.cs \ SparkleAboutController.cs \
SparkleBubbles.cs \ SparkleBubbles.cs \
SparkleBubblesController.cs \ SparkleBubblesController.cs \
SparkleController.cs \ SparkleController.cs \
SparkleControllerBase.cs \
SparkleEntry.cs \ SparkleEntry.cs \
SparkleEventLog.cs \ SparkleEventLog.cs \
SparkleEventLogController.cs \ SparkleEventLogController.cs \
SparkleLinController.cs \ SparkleExtensions.cs \
SparkleSetup.cs \ SparkleSetup.cs \
SparkleSetupController.cs \ SparkleSetupController.cs \
SparkleSetupWindow.cs \ SparkleSetupWindow.cs \
SparkleShare.cs \
SparkleSpinner.cs \ SparkleSpinner.cs \
SparkleStatusIcon.cs \ SparkleStatusIcon.cs \
SparkleStatusIconController.cs \ SparkleStatusIconController.cs \
@ -40,7 +41,7 @@ SOURCES = \
SparkleSetup.cs \ SparkleSetup.cs \
SparkleSetupController.cs \ SparkleSetupController.cs \
SparkleSetupWindow.cs \ SparkleSetupWindow.cs \
SparkleShare.cs \ Program.cs \
SparkleSpinner.cs \ SparkleSpinner.cs \
SparkleStatusIcon.cs \ SparkleStatusIcon.cs \
SparkleStatusIconController.cs \ SparkleStatusIconController.cs \

131
SparkleShare/Program.cs Normal file
View file

@ -0,0 +1,131 @@
// SparkleShare, a collaboration and sharing tool.
// 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 System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using Mono.Unix;
//using Mono.Unix.Native;
using SparkleLib;
using SparkleLib.Options;
namespace SparkleShare {
// This is SparkleShare!
public class Program {
public static SparkleController Controller;
public static SparkleUI UI;
// Short alias for the translations
public static string _ (string s)
{
return Catalog.GetString (s);
}
public static void Main (string [] args)
{
// Parse the command line options
bool show_help = false;
OptionSet option_set = new OptionSet () {
{ "v|version", _("Print version information"), v => { PrintVersion (); } },
{ "h|help", _("Show this help text"), v => show_help = v != null }
};
try {
option_set.Parse (args);
} catch (OptionException e) {
Console.Write ("SparkleShare: ");
Console.WriteLine (e.Message);
Console.WriteLine ("Try `sparkleshare --help' for more information.");
}
if (show_help)
ShowHelp (option_set);
// Initialize the controller this way so that
// there aren't any exceptions in the OS specific UI's
Controller = new SparkleController ();
Controller.Initialize ();
if (Controller != null) {
UI = new SparkleUI ();
UI.Run ();
}
}
// Prints the help output
public static void ShowHelp (OptionSet option_set)
{
Console.WriteLine (" ");
Console.WriteLine (_("SparkleShare, a collaboration and sharing tool."));
Console.WriteLine (_("Copyright (C) 2010 Hylke Bons"));
Console.WriteLine (" ");
Console.WriteLine (_("This program comes with ABSOLUTELY NO WARRANTY."));
Console.WriteLine (" ");
Console.WriteLine (_("This is free software, and you are welcome to redistribute it "));
Console.WriteLine (_("under certain conditions. Please read the GNU GPLv3 for details."));
Console.WriteLine (" ");
Console.WriteLine (_("SparkleShare automatically syncs Git repositories in "));
Console.WriteLine (_("the ~/SparkleShare folder with their remote origins."));
Console.WriteLine (" ");
Console.WriteLine (_("Usage: sparkleshare [start|stop|restart] [OPTION]..."));
Console.WriteLine (_("Sync SparkleShare folder with remote repositories."));
Console.WriteLine (" ");
Console.WriteLine (_("Arguments:"));
option_set.WriteOptionDescriptions (Console.Out);
Environment.Exit (0);
}
// Prints the version information
public static void PrintVersion ()
{
Console.WriteLine (_("SparkleShare " + Defines.VERSION));
Environment.Exit (0);
}
// Strange magic needed by SetProcessName ()
[DllImport ("libc")]
private static extern int prctl (int option, byte [] arg2, IntPtr arg3, IntPtr arg4, IntPtr arg5);
// Sets the Unix process name to 'sparkleshare' instead of 'mono'
private static void SetProcessName (string name)
{
try {
if (prctl (15, Encoding.ASCII.GetBytes (name + "\0"), IntPtr.Zero, IntPtr.Zero, IntPtr.Zero) != 0)
throw new ApplicationException ("Error setting process name: " +
Mono.Unix.Native.Stdlib.GetLastError ());
} catch (EntryPointNotFoundException) {
Console.WriteLine ("SetProcessName: Entry point not found");
}
}
}
}

View file

@ -21,20 +21,20 @@ using System.IO;
using System.Net; using System.Net;
using Gtk; using Gtk;
using Mono.Unix;
namespace SparkleShare { namespace SparkleShare {
public class SparkleAbout : Window { public class SparkleAbout : Window {
public SparkleAboutController Controller = new SparkleAboutController (); public SparkleAboutController Controller;
private Label updates; private Label updates;
// Short alias for the translations // Short alias for the translations
public static string _(string s) public static string _(string s)
{ {
return s; return Catalog.GetString (s);
} }
@ -53,21 +53,22 @@ namespace SparkleShare {
Title = _("About SparkleShare"); Title = _("About SparkleShare");
AppPaintable = true; AppPaintable = true;
MemoryStream MemStream = new MemoryStream(); string image_path = new string [] {SparkleUI.AssetsPath,
Icons.about.Save(MemStream, System.Drawing.Imaging.ImageFormat.Png); "pixmaps", "about.png"}.Combine ();
MemStream.Seek(0, SeekOrigin.Begin);
Realize (); Realize ();
Gdk.Pixbuf buf = new Gdk.Pixbuf(MemStream); Gdk.Pixbuf buf = new Gdk.Pixbuf (image_path);
Gdk.Pixmap map, map2; Gdk.Pixmap map, map2;
buf.RenderPixmapAndMask (out map, out map2, 255); buf.RenderPixmapAndMask (out map, out map2, 255);
GdkWindow.SetBackPixmap (map, false); GdkWindow.SetBackPixmap (map, false);
CreateAbout (); Controller = new SparkleAboutController ();
Controller.NewVersionEvent += delegate (string new_version) { Controller.NewVersionEvent += delegate (string new_version) {
Application.Invoke (delegate { Application.Invoke (delegate {
this.updates.Markup = String.Format ("<span font_size='small' fgcolor='#f57900'>{0}</span>", this.updates.Markup = String.Format ("<span font_size='small' fgcolor='#f57900'>{0}</span>",
String.Format (_("A newer version ({0}) is available!"), new_version)); String.Format (_("A newer version ({0}) is available!"), new_version));
this.updates.ShowAll (); this.updates.ShowAll ();
}); });
}; };
@ -76,6 +77,7 @@ namespace SparkleShare {
Application.Invoke (delegate { Application.Invoke (delegate {
this.updates.Markup = String.Format ("<span font_size='small' fgcolor='#4e9a06'>{0}</span>", this.updates.Markup = String.Format ("<span font_size='small' fgcolor='#4e9a06'>{0}</span>",
_("You are running the latest version.")); _("You are running the latest version."));
this.updates.ShowAll (); this.updates.ShowAll ();
}); });
}; };
@ -84,9 +86,12 @@ namespace SparkleShare {
Application.Invoke (delegate { Application.Invoke (delegate {
this.updates.Markup = String.Format ("<span font_size='small' fgcolor='#4e9a06'>{0}</span>", this.updates.Markup = String.Format ("<span font_size='small' fgcolor='#4e9a06'>{0}</span>",
_("Checking for updates...")); _("Checking for updates..."));
this.updates.ShowAll (); this.updates.ShowAll ();
}); });
}; };
this.CreateAbout ();
} }

View file

@ -68,24 +68,24 @@ namespace SparkleShare {
Uri uri = new Uri ("http://www.sparkleshare.org/version"); Uri uri = new Uri ("http://www.sparkleshare.org/version");
web_client.DownloadStringCompleted += delegate (object o, DownloadStringCompletedEventArgs args) { web_client.DownloadStringCompleted += delegate (object o, DownloadStringCompletedEventArgs args) {
if (args.Error != null) { if (args.Error != null)
Console.WriteLine ("Error during version check: {0}", args.Error.Message); return;
string new_version = args.Result.Trim ();
// Add a little delay, making it seems we're
// actually doing hard work
Thread.Sleep (2 * 1000);
if (RunningVersion.Equals (new_version)) {
if (VersionUpToDateEvent != null)
VersionUpToDateEvent ();
} else { } else {
string new_version = args.Result.Trim (); if (NewVersionEvent != null)
NewVersionEvent (new_version);
// Add a little delay, making it seems we're
// actually doing hard work
Thread.Sleep (2 * 1000);
if (RunningVersion.Equals (new_version)) {
if (VersionUpToDateEvent != null)
VersionUpToDateEvent ();
} else {
if (NewVersionEvent != null)
NewVersionEvent (new_version);
}
} }
this.version_checker.Start (); this.version_checker.Start ();
}; };

View file

@ -30,27 +30,24 @@ namespace SparkleShare {
public SparkleBubbles () public SparkleBubbles ()
{ {
Controller.ShowBubbleEvent += delegate (string title, string subtext, string image_path) { Controller.ShowBubbleEvent += delegate (string title, string subtext, string image_path) {
Notification notification = new Notification () { try {
Timeout = 5 * 1000, Notification notification = new Notification () {
Urgency = Urgency.Low Timeout = 5 * 1000,
}; Urgency = Urgency.Low
};
if (image_path != null)
notification.Icon = new Gdk.Pixbuf (image_path);
else
notification.IconName = "folder-sparkleshare";
if (image_path != null) notification.Show ();
notification.Icon = new Gdk.Pixbuf (image_path);
else
notification.IconName = "folder-sparkleshare";
notification.Show (); } catch (Exception) {
// Ignore exceptions thrown by libnotify,
// they're not important enough to crash
}
}; };
} }
// Checks whether the system allows adding buttons to a notification,
// prevents error messages in Ubuntu.
// new public void AddAction (string action, string label, ActionHandler handler)
// {
// if (Array.IndexOf (Notifications.Global.Capabilities, "actions") > -1)
// base.AddAction (action, label, handler);
// }
} }
} }

View file

@ -27,19 +27,24 @@ namespace SparkleShare {
public SparkleBubblesController () public SparkleBubblesController ()
{ {
SparkleShare.Controller.ConflictNotificationRaised += delegate { Program.Controller.ConflictNotificationRaised += delegate {
if (ShowBubbleEvent != null && SparkleShare.Controller.NotificationsEnabled) ShowBubble ("Ouch! Mid-air collision!",
ShowBubbleEvent ("Ouch! Mid-air collision!", "Don't worry, SparkleShare made a copy of each conflicting file.",
"Don't worry, SparkleShare made a copy of each conflicting file.", null); null);
}; };
SparkleShare.Controller.NotificationRaised += delegate (string user_name, string user_email, Program.Controller.NotificationRaised += delegate (string user_name, string user_email,
string message, string folder_path) { string message, string folder_path) {
ShowBubble (user_name, message,
if (ShowBubbleEvent != null && SparkleShare.Controller.NotificationsEnabled) Program.Controller.GetAvatar (user_email, 36));
ShowBubbleEvent (user_name, message,
SparkleShare.Controller.GetAvatar (user_email, 36));
}; };
} }
public void ShowBubble (string title, string subtext, string image_path)
{
if (ShowBubbleEvent != null && Program.Controller.NotificationsEnabled)
ShowBubbleEvent (title, subtext, image_path);
}
} }
} }

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -23,24 +23,21 @@ using System.Threading;
using Gtk; using Gtk;
using Mono.Unix; using Mono.Unix;
using SparkleLib;
using WebKit; using WebKit;
namespace SparkleShare { namespace SparkleShare {
public class SparkleEventLog : Window { public class SparkleEventLog : Window {
private ScrolledWindow ScrolledWindow; public SparkleEventLogController Controller = new SparkleEventLogController ();
private MenuBar MenuBar;
private WebView WebView;
private string LinkStatus;
private SparkleSpinner Spinner;
private string HTML;
private EventBox LogContent;
private List<SparkleChangeSet> change_sets;
private string selected_log = null;
private ComboBox combo_box;
private HBox layout_horizontal; private HBox layout_horizontal;
private ComboBox combo_box;
private EventBox content_wrapper;
private ScrolledWindow scrolled_window;
private WebView web_view;
private SparkleSpinner spinner;
private string link_status;
// Short alias for the translations // Short alias for the translations
@ -63,49 +60,43 @@ namespace SparkleShare {
DeleteEvent += Close; DeleteEvent += Close;
CreateEvents ();
UpdateEvents (false);
UpdateChooser ();
}
private void CreateEvents ()
{
VBox layout_vertical = new VBox (false, 0); VBox layout_vertical = new VBox (false, 0);
LogContent = new EventBox (); this.spinner = new SparkleSpinner (22);
this.content_wrapper = new EventBox ();
this.scrolled_window = new ScrolledWindow ();
ScrolledWindow = new ScrolledWindow (); this.web_view = new WebView () {
WebView = new WebView () {
Editable = false Editable = false
}; };
WebView.HoveringOverLink += delegate (object o, WebKit.HoveringOverLinkArgs args) { this.web_view.HoveringOverLink += delegate (object o, WebKit.HoveringOverLinkArgs args) {
LinkStatus = args.Link; this.link_status = args.Link;
}; };
WebView.NavigationRequested += delegate (object o, WebKit.NavigationRequestedArgs args) { this.web_view.NavigationRequested += delegate (object o, WebKit.NavigationRequestedArgs args) {
if (args.Request.Uri == LinkStatus) { if (args.Request.Uri == this.link_status) {
// TODO: controller
Process process = new Process (); Process process = new Process ();
process.StartInfo.FileName = "xdg-open"; process.StartInfo.FileName = "xdg-open";
process.StartInfo.Arguments = args.Request.Uri.Replace (" ", "\\ "); // Escape space-characters process.StartInfo.Arguments = args.Request.Uri.Replace (" ", "\\ "); // Escape space-characters
process.Start (); process.Start ();
} else { } else {
Regex regex = new Regex (@"(.+)~(.+)~(.+)"); //TODO: controller
Match match = regex.Match (args.Request.Uri); Regex regex = new Regex (@"(.+)~(.+)~(.+)");
Match match = regex.Match (args.Request.Uri);
if (match.Success) { if (match.Success) {
string folder_name = match.Groups [1].Value; string folder_name = match.Groups [1].Value;
string revision = match.Groups [2].Value; string revision = match.Groups [2].Value;
string note = match.Groups [3].Value.Replace ("%20", " "); string note = match.Groups [3].Value;
Thread thread = new Thread (new ThreadStart (delegate { Thread thread = new Thread (new ThreadStart (delegate {
SparkleShare.Controller.AddNoteToFolder (folder_name, revision, note); Program.Controller.AddNoteToFolder (folder_name, revision, note);
})); }));
thread.Start (); thread.Start ();
} }
} }
// Don't follow HREFs (as this would cause a page refresh) // Don't follow HREFs (as this would cause a page refresh)
@ -113,44 +104,75 @@ namespace SparkleShare {
args.RetVal = 1; args.RetVal = 1;
}; };
ScrolledWindow.Add (WebView); this.scrolled_window.Add (this.web_view);
LogContent.Add (ScrolledWindow); this.content_wrapper.Add (this.spinner);
this.spinner.Start ();
this.layout_horizontal = new HBox (true, 0); this.layout_horizontal = new HBox (true, 0);
this.layout_horizontal.PackStart (new Label (""), true, true, 0); this.layout_horizontal.PackStart (new Label (""), true, true, 0);
this.layout_horizontal.PackStart (new Label (""), true, true, 0); this.layout_horizontal.PackStart (new Label (""), true, true, 0);
layout_vertical.PackStart (layout_horizontal, false, false, 0); layout_vertical.PackStart (this.layout_horizontal, false, false, 0);
layout_vertical.PackStart (LogContent, true, true, 0);
// We have to hide the menubar somewhere...
layout_vertical.PackStart (CreateShortcutsBar (), false, false, 0); layout_vertical.PackStart (CreateShortcutsBar (), false, false, 0);
layout_vertical.PackStart (this.content_wrapper, true, true, 0);
Add (layout_vertical); Add (layout_vertical);
ShowAll (); ShowAll ();
UpdateChooser (null);
UpdateContent (null);
// Hook up the controller events
Controller.UpdateChooserEvent += delegate (string [] folders) {
Application.Invoke (delegate {
UpdateChooser (folders);
});
};
Controller.UpdateContentEvent += delegate (string html) {
Application.Invoke (delegate {
UpdateContent (html);
});
};
Controller.ContentLoadingEvent += delegate {
Application.Invoke (delegate {
if (this.content_wrapper.Child != null)
this.content_wrapper.Remove (this.content_wrapper.Child);
this.content_wrapper.Add (this.spinner);
this.spinner.Start ();
this.content_wrapper.ShowAll ();
});
};
} }
public void UpdateChooser () public void UpdateChooser (string [] folders)
{ {
if (folders == null)
folders = Controller.Folders;
if (this.combo_box != null && this.combo_box.Parent != null) if (this.combo_box != null && this.combo_box.Parent != null)
this.layout_horizontal.Remove (this.combo_box); this.layout_horizontal.Remove (this.combo_box);
this.combo_box = new ComboBox (); this.combo_box = new ComboBox ();
this.layout_horizontal.BorderWidth = 9;
CellRendererText cell = new CellRendererText(); CellRendererText cell = new CellRendererText();
this.combo_box.PackStart (cell, false); this.combo_box.PackStart (cell, false);
this.combo_box.AddAttribute (cell, "text", 0); this.combo_box.AddAttribute (cell, "text", 0);
ListStore store = new ListStore (typeof (string)); ListStore store = new ListStore (typeof (string));
this.combo_box.Model = store;
store.AppendValues (_("All Folders")); store.AppendValues (_("All Folders"));
store.AppendValues ("---"); store.AppendValues ("---");
foreach (string folder_name in SparkleShare.Controller.Folders) foreach (string folder in folders)
store.AppendValues (folder_name); store.AppendValues (folder);
this.combo_box.Model = store;
this.combo_box.Active = 0; this.combo_box.Active = 0;
this.combo_box.RowSeparatorFunc = delegate (TreeModel model, TreeIter iter) { this.combo_box.RowSeparatorFunc = delegate (TreeModel model, TreeIter iter) {
@ -158,116 +180,75 @@ namespace SparkleShare {
return (item == "---"); return (item == "---");
}; };
if (this.selected_log != null &&
!SparkleShare.Controller.Folders.Contains (this.selected_log)) {
this.selected_log = null;
}
this.combo_box.Changed += delegate { this.combo_box.Changed += delegate {
TreeIter iter; TreeIter iter;
this.combo_box.GetActiveIter (out iter); this.combo_box.GetActiveIter (out iter);
string selection = (string) this.combo_box.Model.GetValue (iter, 0); string selection = (string) this.combo_box.Model.GetValue (iter, 0);
if (selection.Equals (_("All Folders"))) if (selection.Equals (_("All Folders")))
this.selected_log = null; Controller.SelectedFolder = null;
else else
this.selected_log = selection; Controller.SelectedFolder = selection;
UpdateEvents (false);
}; };
this.layout_horizontal.BorderWidth = 9;
this.layout_horizontal.PackStart (this.combo_box, true, true, 0); this.layout_horizontal.PackStart (this.combo_box, true, true, 0);
this.layout_horizontal.ShowAll (); this.layout_horizontal.ShowAll ();
} }
public void UpdateEvents () public void UpdateContent (string html)
{ {
UpdateEvents (true);
}
public void UpdateEvents (bool silent)
{
if (!silent) {
LogContent.Remove (LogContent.Child);
Spinner = new SparkleSpinner (22);
LogContent.Add (Spinner);
LogContent.ShowAll ();
}
Thread thread = new Thread (new ThreadStart (delegate { Thread thread = new Thread (new ThreadStart (delegate {
Stopwatch watch = new Stopwatch (); if (html == null)
watch.Start (); html = Controller.HTML;
this.change_sets = SparkleShare.Controller.GetLog (this.selected_log);
GenerateHTML ();
watch.Stop ();
// A short delay is less annoying than if (html == null)
// a flashing window return;
if (watch.ElapsedMilliseconds < 500 && !silent)
Thread.Sleep (500 - (int) watch.ElapsedMilliseconds);
AddHTML (); html = html.Replace ("<!-- $body-font-size -->", (double) (Style.FontDescription.Size / 1024 + 3) + "px");
html = html.Replace ("<!-- $day-entry-header-font-size -->", (Style.FontDescription.Size / 1024 + 3) + "px");
html = html.Replace ("<!-- $a-color -->", "#0085cf");
html = html.Replace ("<!-- $a-hover-color -->", "#009ff8");
html = html.Replace ("<!-- $body-font-family -->", "\"" + Style.FontDescription.Family + "\"");
html = html.Replace ("<!-- $body-color -->", SparkleUIHelpers.GdkColorToHex (Style.Foreground (StateType.Normal)));
html = html.Replace ("<!-- $body-background-color -->", SparkleUIHelpers.GdkColorToHex (new TreeView ().Style.Base (StateType.Normal)));
html = html.Replace ("<!-- $day-entry-header-background-color -->", SparkleUIHelpers.GdkColorToHex (Style.Background (StateType.Normal)));
html = html.Replace ("<!-- $secondary-font-color -->", SparkleUIHelpers.GdkColorToHex (Style.Foreground (StateType.Insensitive)));
html = html.Replace ("<!-- $small-color -->", SparkleUIHelpers.GdkColorToHex (Style.Foreground (StateType.Insensitive)));
html = html.Replace ("<!-- $no-buddy-icon-background-image -->", "file://" +
new string [] {SparkleUI.AssetsPath, "icons",
"hicolor", "32x32", "status", "avatar-default.png"}.Combine ());
html = html.Replace ("<!-- $document-added-background-image -->", "file://" +
new string [] {SparkleUI.AssetsPath, "icons",
"hicolor", "12x12", "status", "document-added.png"}.Combine ());
html = html.Replace ("<!-- $document-edited-background-image -->", "file://" +
new string [] {SparkleUI.AssetsPath, "icons",
"hicolor", "12x12", "status", "document-edited.png"}.Combine ());
html = html.Replace ("<!-- $document-deleted-background-image -->", "file://" +
new string [] {SparkleUI.AssetsPath, "icons",
"hicolor", "12x12", "status", "document-deleted.png"}.Combine ());
html = html.Replace ("<!-- $document-moved-background-image -->", "file://" +
new string [] {SparkleUI.AssetsPath, "icons",
"hicolor", "12x12", "status", "document-moved.png"}.Combine ());
Application.Invoke (delegate {
this.spinner.Stop ();
this.web_view.LoadString (html, null, null, "file://");
this.content_wrapper.Remove (this.content_wrapper.Child);
this.content_wrapper.Add (this.scrolled_window);
this.content_wrapper.ShowAll ();
});
})); }));
thread.Start (); thread.Start ();
} }
private void GenerateHTML ()
{
HTML = SparkleShare.Controller.GetHTMLLog (this.change_sets);
HTML = HTML.Replace ("<!-- $body-font-size -->", (double) (Style.FontDescription.Size / 1024 + 3) + "px");
HTML = HTML.Replace ("<!-- $day-entry-header-font-size -->", (Style.FontDescription.Size / 1024 + 3) + "px");
HTML = HTML.Replace ("<!-- $a-color -->", "#0085cf");
HTML = HTML.Replace ("<!-- $a-hover-color -->", "#009ff8");
HTML = HTML.Replace ("<!-- $body-font-family -->", "\"" + Style.FontDescription.Family + "\"");
HTML = HTML.Replace ("<!-- $body-color -->", SparkleUIHelpers.GdkColorToHex (Style.Foreground (StateType.Normal)));
HTML = HTML.Replace ("<!-- $body-background-color -->", SparkleUIHelpers.GdkColorToHex (new TreeView ().Style.Base (StateType.Normal)));
HTML = HTML.Replace ("<!-- $day-entry-header-background-color -->", SparkleUIHelpers.GdkColorToHex (Style.Background (StateType.Normal)));
HTML = HTML.Replace ("<!-- $secondary-font-color -->", SparkleUIHelpers.GdkColorToHex (Style.Foreground (StateType.Insensitive)));
HTML = HTML.Replace ("<!-- $small-color -->", SparkleUIHelpers.GdkColorToHex (Style.Foreground (StateType.Insensitive)));
HTML = HTML.Replace ("<!-- $no-buddy-icon-background-image -->", "file://" +
SparkleHelpers.CombineMore (Defines.PREFIX, "share", "sparkleshare", "icons",
"hicolor", "32x32", "status", "avatar-default.png"));
HTML = HTML.Replace ("<!-- $document-added-background-image -->", "file://" +
SparkleHelpers.CombineMore (Defines.PREFIX, "share", "sparkleshare", "icons",
"hicolor", "12x12", "status", "document-added.png"));
HTML = HTML.Replace ("<!-- $document-edited-background-image -->", "file://" +
SparkleHelpers.CombineMore (Defines.PREFIX, "share", "sparkleshare", "icons",
"hicolor", "12x12", "status", "document-edited.png"));
HTML = HTML.Replace ("<!-- $document-deleted-background-image -->", "file://" +
SparkleHelpers.CombineMore (Defines.PREFIX, "share", "sparkleshare", "icons",
"hicolor", "12x12", "status", "document-deleted.png"));
HTML = HTML.Replace ("<!-- $document-moved-background-image -->", "file://" +
SparkleHelpers.CombineMore (Defines.PREFIX, "share", "sparkleshare", "icons",
"hicolor", "12x12", "status", "document-moved.png"));
}
private void AddHTML ()
{
Application.Invoke (delegate {
Spinner.Stop ();
LogContent.Remove (LogContent.Child);
WebView.LoadString (HTML, null, null, "file://");
LogContent.Add (ScrolledWindow);
LogContent.ShowAll ();
});
}
public void Close (object o, DeleteEventArgs args) public void Close (object o, DeleteEventArgs args)
{ {
HideAll (); HideAll ();
args.RetVal = true; args.RetVal = true;
// TODO: window positions aren't saved
} }
@ -275,7 +256,7 @@ namespace SparkleShare {
{ {
// Adds a hidden menubar that contains to enable keyboard // Adds a hidden menubar that contains to enable keyboard
// shortcuts to close the log // shortcuts to close the log
MenuBar = new MenuBar (); MenuBar menu_bar = new MenuBar ();
MenuItem file_item = new MenuItem ("File"); MenuItem file_item = new MenuItem ("File");
@ -304,15 +285,14 @@ namespace SparkleShare {
file_item.Submenu = file_menu; file_item.Submenu = file_menu;
MenuBar.Append (file_item); menu_bar.Append (file_item);
// Hacky way to hide the menubar, but the accellerators // Hacky way to hide the menubar, but the accellerators
// will simply be disabled when using Hide () // will simply be disabled when using Hide ()
MenuBar.HeightRequest = 1; menu_bar.HeightRequest = 1;
MenuBar.ModifyBg (StateType.Normal, Style.Background (StateType.Normal)); menu_bar.ModifyBg (StateType.Normal, Style.Background (StateType.Normal));
return MenuBar; return menu_bar;
} }
} }
} }

View file

@ -69,14 +69,14 @@ namespace SparkleShare {
public string HTML { public string HTML {
get { get {
List<SparkleChangeSet> change_sets = SparkleShare.Controller.GetLog (this.selected_folder); List<SparkleChangeSet> change_sets = Program.Controller.GetLog (this.selected_folder);
return SparkleShare.Controller.GetHTMLLog (change_sets); return Program.Controller.GetHTMLLog (change_sets);
} }
} }
public string [] Folders { public string [] Folders {
get { get {
return SparkleShare.Controller.Folders.ToArray (); return Program.Controller.Folders.ToArray ();
} }
} }
@ -86,19 +86,19 @@ namespace SparkleShare {
public SparkleEventLogController () public SparkleEventLogController ()
{ {
SparkleShare.Controller.AvatarFetched += delegate { Program.Controller.AvatarFetched += delegate {
if (UpdateContentEvent != null) if (UpdateContentEvent != null)
UpdateContentEvent (HTML); UpdateContentEvent (HTML);
}; };
SparkleShare.Controller.OnIdle += delegate { Program.Controller.OnIdle += delegate {
if (UpdateContentEvent != null) if (UpdateContentEvent != null)
UpdateContentEvent (HTML); UpdateContentEvent (HTML);
}; };
SparkleShare.Controller.FolderListChanged += delegate { Program.Controller.FolderListChanged += delegate {
if (this.selected_folder != null && if (this.selected_folder != null &&
!SparkleShare.Controller.Folders.Contains (this.selected_folder)) { !Program.Controller.Folders.Contains (this.selected_folder)) {
this.selected_folder = null; this.selected_folder = null;
} }
@ -110,7 +110,7 @@ namespace SparkleShare {
UpdateContentEvent (HTML); UpdateContentEvent (HTML);
}; };
SparkleShare.Controller.NotificationRaised += delegate { Program.Controller.NotificationRaised += delegate {
if (UpdateContentEvent != null) if (UpdateContentEvent != null)
UpdateContentEvent (HTML); UpdateContentEvent (HTML);
}; };

View file

@ -0,0 +1,35 @@
// SparkleShare, a collaboration and sharing tool.
// 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 System;
using System.IO;
namespace SparkleShare {
public static class Extensions {
public static string Combine (this String [] parts)
{
string new_path = "";
foreach (string part in parts)
new_path = Path.Combine (new_path, part);
return new_path;
}
}
}

View file

@ -73,8 +73,11 @@ namespace SparkleShare {
// from the Internet category if needed // from the Internet category if needed
public override void InstallLauncher () public override void InstallLauncher ()
{ {
string apps_path = SparkleHelpers.CombineMore (SparklePaths.HomePath, ".local", "share", "applications"); string apps_path =
string desktopfile_path = SparkleHelpers.CombineMore (apps_path, "sparkleshare.desktop"); new string [] {SparkleConfig.DefaultConfig.HomePath,
".local", "share", "applications"}.Combine ();
string desktopfile_path = Path.Combine (apps_path, "sparkleshare.desktop");
if (!File.Exists (desktopfile_path)) { if (!File.Exists (desktopfile_path)) {
if (!Directory.Exists (apps_path)) if (!Directory.Exists (apps_path))
@ -104,8 +107,8 @@ namespace SparkleShare {
// list of bookmarked places // list of bookmarked places
public override void AddToBookmarks () public override void AddToBookmarks ()
{ {
string bookmarks_file_path = Path.Combine (SparklePaths.HomePath, ".gtk-bookmarks"); string bookmarks_file_path = Path.Combine (SparkleConfig.DefaultConfig.HomePath, ".gtk-bookmarks");
string sparkleshare_bookmark = "file://" + SparklePaths.SparklePath + " SparkleShare"; string sparkleshare_bookmark = "file://" + SparkleConfig.DefaultConfig.FoldersPath + " SparkleShare";
if (File.Exists (bookmarks_file_path)) { if (File.Exists (bookmarks_file_path)) {
StreamReader reader = new StreamReader (bookmarks_file_path); StreamReader reader = new StreamReader (bookmarks_file_path);
@ -114,12 +117,12 @@ namespace SparkleShare {
if (!bookmarks.Contains (sparkleshare_bookmark)) { if (!bookmarks.Contains (sparkleshare_bookmark)) {
TextWriter writer = File.AppendText (bookmarks_file_path); TextWriter writer = File.AppendText (bookmarks_file_path);
writer.WriteLine ("file://" + SparklePaths.SparklePath + " SparkleShare"); writer.WriteLine ("file://" + SparkleConfig.DefaultConfig.FoldersPath + " SparkleShare");
writer.Close (); writer.Close ();
} }
} else { } else {
StreamWriter writer = new StreamWriter (bookmarks_file_path); StreamWriter writer = new StreamWriter (bookmarks_file_path);
writer.WriteLine ("file://" + SparklePaths.SparklePath + " SparkleShare"); writer.WriteLine ("file://" + SparkleConfig.DefaultConfig.FoldersPath + " SparkleShare");
writer.Close (); writer.Close ();
} }
} }
@ -128,13 +131,14 @@ namespace SparkleShare {
// Creates the SparkleShare folder in the user's home folder // Creates the SparkleShare folder in the user's home folder
public override bool CreateSparkleShareFolder () public override bool CreateSparkleShareFolder ()
{ {
if (!Directory.Exists (SparklePaths.SparklePath)) { if (!Directory.Exists (SparkleConfig.DefaultConfig.FoldersPath)) {
Directory.CreateDirectory (SparklePaths.SparklePath); Directory.CreateDirectory (SparkleConfig.DefaultConfig.FoldersPath);
SparkleHelpers.DebugInfo ("Controller", "Created '" + SparklePaths.SparklePath + "'"); SparkleHelpers.DebugInfo ("Controller", "Created '" + SparkleConfig.DefaultConfig.FoldersPath + "'");
string gvfs_command_path = SparkleHelpers.CombineMore (Path.VolumeSeparatorChar.ToString (), string gvfs_command_path =
"usr", "bin", "gvfs-set-attribute"); new string [] {Path.VolumeSeparatorChar.ToString (),
"usr", "bin", "gvfs-set-attribute"}.Combine ();
// Add a special icon to the SparkleShare folder // Add a special icon to the SparkleShare folder
if (File.Exists (gvfs_command_path)) { if (File.Exists (gvfs_command_path)) {
@ -145,12 +149,12 @@ namespace SparkleShare {
process.StartInfo.FileName = "gvfs-set-attribute"; process.StartInfo.FileName = "gvfs-set-attribute";
// Clear the custom (legacy) icon path // Clear the custom (legacy) icon path
process.StartInfo.Arguments = "-t unset " + SparklePaths.SparklePath + " metadata::custom-icon"; process.StartInfo.Arguments = "-t unset " + SparkleConfig.DefaultConfig.FoldersPath + " metadata::custom-icon";
process.Start (); process.Start ();
process.WaitForExit (); process.WaitForExit ();
// Give the SparkleShare folder an icon name, so that it scales // Give the SparkleShare folder an icon name, so that it scales
process.StartInfo.Arguments = SparklePaths.SparklePath + " metadata::custom-icon-name 'folder-sparkleshare'"; process.StartInfo.Arguments = SparkleConfig.DefaultConfig.FoldersPath + " metadata::custom-icon-name 'folder-sparkleshare'";
process.Start (); process.Start ();
process.WaitForExit (); process.WaitForExit ();
} }
@ -164,13 +168,13 @@ namespace SparkleShare {
public override string EventLogHTML { public override string EventLogHTML {
get { get {
string path = SparkleHelpers.CombineMore (Defines.PREFIX, string path = new string [] {Defines.PREFIX,
"share", "sparkleshare", "html", "event-log.html"); "share", "sparkleshare", "html", "event-log.html"}.Combine ();
string html = String.Join (Environment.NewLine, File.ReadAllLines (path)); string html = String.Join (Environment.NewLine, File.ReadAllLines (path));
html = html.Replace ("<!-- $jquery-url -->", "file://" + html = html.Replace ("<!-- $jquery-url -->", "file://" +
SparkleHelpers.CombineMore (Defines.PREFIX, "share", "sparkleshare", "html", "jquery.js")); new string [] {Defines.PREFIX, "share", "sparkleshare", "html", "jquery.js"}.Combine ());
return html; return html;
} }
@ -179,8 +183,8 @@ namespace SparkleShare {
public override string DayEntryHTML { public override string DayEntryHTML {
get { get {
string path = SparkleHelpers.CombineMore (Defines.PREFIX, string path = new string [] {Defines.PREFIX,
"share", "sparkleshare", "html", "day-entry.html"); "share", "sparkleshare", "html", "day-entry.html"}.Combine ();
return String.Join (Environment.NewLine, File.ReadAllLines (path)); return String.Join (Environment.NewLine, File.ReadAllLines (path));
} }
@ -189,8 +193,8 @@ namespace SparkleShare {
public override string EventEntryHTML { public override string EventEntryHTML {
get { get {
string path = SparkleHelpers.CombineMore (Defines.PREFIX, string path = new string [] {Defines.PREFIX,
"share", "sparkleshare", "html", "event-entry.html"); "share", "sparkleshare", "html", "event-entry.html"}.Combine ();
return String.Join (Environment.NewLine, File.ReadAllLines (path)); return String.Join (Environment.NewLine, File.ReadAllLines (path));
} }
@ -199,7 +203,7 @@ namespace SparkleShare {
public override void OpenSparkleShareFolder (string subfolder) public override void OpenSparkleShareFolder (string subfolder)
{ {
string folder = Path.Combine (SparklePaths.SparklePath, subfolder); string folder = Path.Combine (SparkleConfig.DefaultConfig.FoldersPath, subfolder);
Process process = new Process (); Process process = new Process ();
process.StartInfo.FileName = "xdg-open"; process.StartInfo.FileName = "xdg-open";

View file

@ -43,10 +43,8 @@ namespace SparkleShare {
private Button SyncButton; private Button SyncButton;
private Table Table; private Table Table;
private ProgressBar progress_bar = new ProgressBar ();
private ProgressBar progress_bar = new ProgressBar () { PulseStep = 0.01 };
private Timer progress_bar_pulse_timer = new Timer () { Interval = 25, Enabled = true };
// Short alias for the translations // Short alias for the translations
public static string _ (string s) public static string _ (string s)
@ -64,7 +62,7 @@ namespace SparkleShare {
Reset (); Reset ();
switch (type) { switch (type) {
case PageType.Setup: case PageType.Setup: {
Header = _("Welcome to SparkleShare!"); Header = _("Welcome to SparkleShare!");
Description = _("Before we can create a SparkleShare folder on this " + Description = _("Before we can create a SparkleShare folder on this " +
@ -79,12 +77,12 @@ namespace SparkleShare {
Xalign = 0 Xalign = 0
}; };
NameEntry = new Entry (SparkleShare.Controller.UserName); NameEntry = new Entry (Controller.GuessedUserName);
NameEntry.Changed += delegate { NameEntry.Changed += delegate {
CheckSetupPage (); CheckSetupPage ();
}; };
EmailEntry = new Entry (); EmailEntry = new Entry (Controller.GuessedUserEmail);
EmailEntry.Changed += delegate { EmailEntry.Changed += delegate {
CheckSetupPage (); CheckSetupPage ();
}; };
@ -116,13 +114,14 @@ namespace SparkleShare {
CheckSetupPage (); CheckSetupPage ();
break; break;
}
case PageType.Add: case PageType.Add: {
Header = _("Where is your remote folder?"); Header = _("Where is your project?");
Table = new Table (6, 2, false) { Table = new Table (6, 2, false) {
RowSpacing = 12 RowSpacing = 0
}; };
HBox layout_server = new HBox (true, 0); HBox layout_server = new HBox (true, 0);
@ -150,8 +149,8 @@ namespace SparkleShare {
ListStore server_store = new ListStore (typeof (string)); ListStore server_store = new ListStore (typeof (string));
//TODO foreach (string host in SparkleShare.Controller.PreviousHosts) foreach (string host in Program.Controller.PreviousHosts)
// server_store.AppendValues (host); server_store.AppendValues (host);
ServerEntry.Completion.Model = server_store; ServerEntry.Completion.Model = server_store;
ServerEntry.Completion.TextColumn = 0; ServerEntry.Completion.TextColumn = 0;
@ -173,11 +172,7 @@ namespace SparkleShare {
Table.Attach (layout_server, 0, 2, 1, 2); Table.Attach (layout_server, 0, 2, 1, 2);
// Github radiobutton // Github radiobutton
string github_text = "<b>" + "Github" + "</b>\n" + string github_text = "<b>" + "Github" + "</b>";
"<span fgcolor='" + SecondaryTextColor + "' size='small'>" +
_("Free hosting for Free and Open Source Software projects.") + "\n" +
_("Also has paid accounts for extra private space and bandwidth.") +
"</span>";
RadioButton radio_button_github = new RadioButton (radio_button, github_text); RadioButton radio_button_github = new RadioButton (radio_button, github_text);
(radio_button_github.Child as Label).UseMarkup = true; (radio_button_github.Child as Label).UseMarkup = true;
@ -190,11 +185,7 @@ namespace SparkleShare {
// Gitorious radiobutton // Gitorious radiobutton
string gitorious_text = "<b>" + _("Gitorious") + "</b>\n" + string gitorious_text = "<b>" + _("Gitorious") + "</b>";
"<span fgcolor='" + SecondaryTextColor + "' size='small'>" +
_("Completely Free as in Freedom infrastructure.") + "\n" +
_("Free accounts for Free and Open Source projects.") +
"</span>";
RadioButton radio_button_gitorious = new RadioButton (radio_button, gitorious_text); RadioButton radio_button_gitorious = new RadioButton (radio_button, gitorious_text);
(radio_button_gitorious.Child as Label).UseMarkup = true; (radio_button_gitorious.Child as Label).UseMarkup = true;
@ -207,11 +198,7 @@ namespace SparkleShare {
// GNOME radiobutton // GNOME radiobutton
string gnome_text = "<b>" + _("The GNOME Project") + "</b>\n"+ string gnome_text = "<b>" + _("The GNOME Project") + "</b>";
"<span fgcolor='" + SecondaryTextColor + "' size='small'>" +
_("GNOME is an easy to understand interface to your computer.") + "\n" +
_("Select this option if youre a developer or designer working on GNOME.") +
"</span>";
RadioButton radio_button_gnome = new RadioButton (radio_button, gnome_text); RadioButton radio_button_gnome = new RadioButton (radio_button, gnome_text);
(radio_button_gnome.Child as Label).UseMarkup = true; (radio_button_gnome.Child as Label).UseMarkup = true;
@ -236,6 +223,15 @@ namespace SparkleShare {
FolderEntry = new SparkleEntry (); FolderEntry = new SparkleEntry ();
FolderEntry.ExampleText = _("Folder"); FolderEntry.ExampleText = _("Folder");
FolderEntry.Completion = new EntryCompletion();
ListStore folder_store = new ListStore (typeof (string));
//foreach (string host in Program.Controller.FolderPaths)
// folder_store.AppendValues (host);
FolderEntry.Completion.Model = folder_store;
FolderEntry.Completion.TextColumn = 0;
FolderEntry.Changed += delegate { FolderEntry.Changed += delegate {
CheckAddPage (); CheckAddPage ();
@ -245,7 +241,10 @@ namespace SparkleShare {
layout_folder.PackStart (FolderEntry, true, true, 0); layout_folder.PackStart (FolderEntry, true, true, 0);
Table.Attach (layout_folder, 0, 2, 5, 6); Table.Attach (layout_folder, 0, 2, 5, 6);
Add (Table);
VBox box = new VBox (false, 0);
box.PackStart (Table, false, false, 0);
Add (box);
// Cancel button // Cancel button
Button cancel_button = new Button (_("Cancel")); Button cancel_button = new Button (_("Cancel"));
@ -256,7 +255,7 @@ namespace SparkleShare {
// Sync button // Sync button
SyncButton = new Button (_("Sync")); SyncButton = new Button (_("Add"));
SyncButton.Clicked += delegate { SyncButton.Clicked += delegate {
string server = ServerEntry.Text; string server = ServerEntry.Text;
@ -280,27 +279,33 @@ namespace SparkleShare {
CheckAddPage (); CheckAddPage ();
break; break;
}
case PageType.Syncing: case PageType.Syncing: {
Header = String.Format (_("Syncing folder {0}’…"), Controller.SyncingFolder); Header = String.Format (_("Adding project {0}’…"), Controller.SyncingFolder);
Description = _("This may take a while." + Environment.NewLine) + Description = _("This may take a while." + Environment.NewLine) +
_("Are you sure its not coffee o'clock?"); _("Are you sure its not coffee o'clock?");
Button button = new Button () { Button finish_button = new Button () {
Sensitive = false, Sensitive = false,
Label = _("Finish") Label = _("Finish")
}; };
button.Clicked += delegate { Button cancel_button = new Button () {
Close (); Label = _("Cancel")
}; };
AddButton (button); cancel_button.Clicked += delegate {
Controller.SyncingCancelled ();
};
this.progress_bar_pulse_timer.Elapsed += delegate { AddButton (cancel_button);
AddButton (finish_button);
Controller.UpdateProgressBarEvent += delegate (double percentage) {
Application.Invoke (delegate { Application.Invoke (delegate {
progress_bar.Pulse (); this.progress_bar.Fraction = percentage / 100;
}); });
}; };
@ -313,32 +318,59 @@ namespace SparkleShare {
Add (bar_wrapper); Add (bar_wrapper);
break; break;
}
case PageType.Error: case PageType.Error: {
string n = Environment.NewLine;
Header = _("Something went wrong") + "…"; Header = _("Something went wrong") + "…";
Description = "We don't know exactly what the problem is, " +
"but we can try to help you pinpoint it."; VBox points = new VBox (false, 0);
Image list_point_one = new Image (SparkleUIHelpers.GetIcon ("list-point", 16)) { };
Image list_point_two = new Image (SparkleUIHelpers.GetIcon ("list-point", 16)) { };
Image list_point_three = new Image (SparkleUIHelpers.GetIcon ("list-point", 16)) { };
Label label_one = new Label () {
Text = "First, have you tried turning it off and on again?",
Wrap = true,
Xalign = 0
};
Label label_two = new Label () {
Markup = "<b>" + Controller.PreviousUrl + "</b> is the address we've compiled. " +
"Does this look alright?",
Wrap = true,
Xalign = 0
};
Label label_three = new Label () {
Text = "The host needs to know who you are. Did you upload the key that's in " +
"your SparkleShare folder?",
Wrap = true,
Xalign = 0
};
points.PackStart (new Label ("Please check the following:") { Xalign = 0 }, false, false, 6);
HBox point_one = new HBox (false, 0);
point_one.PackStart (list_point_one, false, false, 0);
point_one.PackStart (label_one, true, true, 12);
points.PackStart (point_one, false, false, 12);
HBox point_two = new HBox (false, 0);
point_two.PackStart (list_point_two, false, false, 0);
point_two.PackStart (label_two, true, true, 12);
points.PackStart (point_two, false, false, 12);
HBox point_three = new HBox (false, 0);
point_three.PackStart (list_point_three, false, false, 0);
point_three.PackStart (label_three, true, true, 12);
points.PackStart (point_three, false, false, 12);
points.PackStart (new Label (""), true, true, 0);
Label l = new Label ( Button try_again_button = new Button (_("Try Again…")) {
"First, have you tried turning it off and on again?" + n +
n +
Controller.SyncingFolder +" is the address we've compiled from the information " +
"you entered. Does this look correct?" + n +
n +
"The host needs to know who you are. Have you uploaded the key that sits in your SparkleShare folder?");
l.Xpad = 12;
l.Wrap = true;
Button try_again_button = new Button (_("Try Again")) {
Sensitive = true Sensitive = true
}; };
@ -347,34 +379,36 @@ namespace SparkleShare {
}; };
AddButton (try_again_button); AddButton (try_again_button);
Add (l); Add (points);
break; break;
}
case PageType.Finished: case PageType.Finished: {
UrgencyHint = true; UrgencyHint = true;
if (!HasToplevelFocus) { if (!HasToplevelFocus) {
string title = String.Format (_("{0} has been successfully added"), Controller.SyncingFolder); string title = String.Format (_("{0} has been successfully added"), Controller.SyncingFolder);
string subtext = _(""); string subtext = "";
//TODO new SparkleBubble (title, subtext).Show (); SparkleUI.Bubbles.Controller.ShowBubble (title, subtext, null);
} }
Header = _("Folder synced successfully!"); Header = _("Project successfully added!");
Description = _("Access the synced files from your SparkleShare folder."); Description = _("Access the files from your SparkleShare folder.");
// A button that opens the synced folder // A button that opens the synced folder
Button open_folder_button = new Button (_("Open Folder")); Button open_folder_button = new Button (_("Open Folder"));
open_folder_button.Clicked += delegate { open_folder_button.Clicked += delegate {
SparkleShare.Controller.OpenSparkleShareFolder (Controller.SyncingFolder); Program.Controller.OpenSparkleShareFolder (Controller.SyncingFolder);
}; };
Button finish_button = new Button (_("Finish")); Button finish_button = new Button (_("Finish"));
finish_button.Clicked += delegate { finish_button.Clicked += delegate {
Controller.FinishedPageCompleted ();
Close (); Close ();
}; };
@ -386,10 +420,116 @@ namespace SparkleShare {
break; break;
} }
case PageType.Tutorial: {
switch (Controller.TutorialPageNumber) {
case 1: {
Header = _("What's happening next?");
Description = _("SparkleShare creates a special folder in your personal folder " +
"that will keep track of your projects.");
Button skip_tutorial_button = new Button (_("Skip Tutorial"));
skip_tutorial_button.Clicked += delegate {
Controller.TutorialSkipped ();
};
Button continue_button = new Button (_("Continue"));
continue_button.Clicked += delegate {
Controller.TutorialPageCompleted ();
};
Image slide = SparkleUIHelpers.GetImage ("tutorial-slide-1.png");
Add (slide);
AddButton (skip_tutorial_button);
AddButton (continue_button);
break;
}
case 2: {
Header = _("Sharing files with others");
Description = _("All files added to your project folders are synced with the host " +
"automatically, as well as with your collaborators.");
Button continue_button = new Button (_("Continue"));
continue_button.Clicked += delegate {
Controller.TutorialPageCompleted ();
};
Image slide = SparkleUIHelpers.GetImage ("tutorial-slide-2.png");
Add (slide);
AddButton (continue_button);
break;
}
case 3: {
Header = _("The status icon is here to help");
Description = _("It shows the syncing process status, " +
"and contains links to your projects and the event log.");
Button continue_button = new Button (_("Continue"));
continue_button.Clicked += delegate {
Controller.TutorialPageCompleted ();
};
Image slide = SparkleUIHelpers.GetImage ("tutorial-slide-3.png");
Add (slide);
AddButton (continue_button);
break;
}
case 4: {
Header = _("Adding projects to SparkleShare");
Description = _("Just click this button when you see it on the web, and " +
"the project will be automatically added:");
Label label = new Label (_("…or select <b>Add Project…</b> from the status icon menu " +
"to add one by hand.")) {
Wrap = true,
Xalign = 0,
UseMarkup = true
};
Image slide = SparkleUIHelpers.GetImage ("tutorial-slide-4.png");
Button add_project_button = new Button (_("Add Project…"));
add_project_button.Clicked += delegate {
Controller.TutorialPageCompleted ();
};
Button finish_button = new Button (_("Finish"));
finish_button.Clicked += delegate {
Close ();
};
VBox box = new VBox (false, 0);
box.Add (slide);
box.Add (label);
Add (box);
AddButton (add_project_button);
AddButton (finish_button);
break;
}
}
break;
}
}
ShowAll (); ShowAll ();
}); });
}; };
} }
@ -398,7 +538,7 @@ namespace SparkleShare {
private void CheckSetupPage () private void CheckSetupPage ()
{ {
if (NameEntry.Text.Length > 0 && if (NameEntry.Text.Length > 0 &&
SparkleShare.Controller.IsValidEmail (EmailEntry.Text)) { Program.Controller.IsValidEmail (EmailEntry.Text)) {
NextButton.Sensitive = true; NextButton.Sensitive = true;
} else { } else {

View file

@ -25,7 +25,8 @@ namespace SparkleShare {
Add, Add,
Syncing, Syncing,
Error, Error,
Finished Finished,
Tutorial
} }
@ -33,6 +34,22 @@ namespace SparkleShare {
public event ChangePageEventHandler ChangePageEvent; public event ChangePageEventHandler ChangePageEvent;
public delegate void ChangePageEventHandler (PageType page); public delegate void ChangePageEventHandler (PageType page);
public event UpdateProgressBarEventHandler UpdateProgressBarEvent;
public delegate void UpdateProgressBarEventHandler (double percentage);
public int TutorialPageNumber {
get {
return this.tutorial_page_number;
}
}
public string PreviousUrl {
get {
return this.previous_url;
}
}
public string PreviousServer { public string PreviousServer {
get { get {
@ -58,11 +75,30 @@ namespace SparkleShare {
} }
} }
private string previous_server = ""; public string GuessedUserName {
private string previous_folder = ""; get {
private string syncing_folder = ""; return Program.Controller.UserName;
}
}
public string GuessedUserEmail {
get {
if (Program.Controller.UserEmail.Equals ("Unknown"))
return "";
else
return Program.Controller.UserEmail;
}
}
private string previous_server = "";
private string previous_folder = "";
private string previous_url = "";
private string syncing_folder = "";
private int tutorial_page_number = 1;
private PageType previous_page; private PageType previous_page;
public SparkleSetupController () public SparkleSetupController ()
{ {
ChangePageEvent += delegate (PageType page) { ChangePageEvent += delegate (PageType page) {
@ -94,34 +130,59 @@ namespace SparkleShare {
Program.Controller.UpdateState (); Program.Controller.UpdateState ();
if (ChangePageEvent != null) if (ChangePageEvent != null)
ChangePageEvent (PageType.Add); ChangePageEvent (PageType.Tutorial);
}
public void TutorialPageCompleted ()
{
this.tutorial_page_number++;
if (ChangePageEvent != null)
ChangePageEvent (PageType.Tutorial);
}
public void TutorialSkipped ()
{
this.tutorial_page_number = 4;
if (ChangePageEvent != null)
ChangePageEvent (PageType.Tutorial);
} }
public void AddPageCompleted (string server, string folder_name) public void AddPageCompleted (string server, string folder_name)
{ {
this.syncing_folder = folder_name; this.syncing_folder = Path.GetFileNameWithoutExtension (folder_name);
this.previous_server = server; this.previous_server = server;
this.previous_folder = folder_name; this.previous_folder = folder_name;
if (ChangePageEvent != null) if (ChangePageEvent != null)
ChangePageEvent (PageType.Syncing); ChangePageEvent (PageType.Syncing);
Program.Controller.FolderFetched += (target_folder_name) => { Program.Controller.FolderFetched += delegate {
this.syncing_folder = target_folder_name;
if (ChangePageEvent != null) if (ChangePageEvent != null)
ChangePageEvent (PageType.Finished); ChangePageEvent (PageType.Finished);
this.syncing_folder = "";
}; };
Program.Controller.FolderFetchError += delegate { Program.Controller.FolderFetchError += delegate (string remote_url) {
this.previous_url = remote_url;
if (ChangePageEvent != null) if (ChangePageEvent != null)
ChangePageEvent (PageType.Error); ChangePageEvent (PageType.Error);
this.syncing_folder = ""; this.syncing_folder = "";
}; };
Program.Controller.FolderFetching += delegate (double percentage) {
if (UpdateProgressBarEvent != null)
UpdateProgressBarEvent (percentage);
};
Program.Controller.FetchFolder (server, this.syncing_folder); Program.Controller.FetchFolder (server, folder_name);
} }
@ -132,6 +193,15 @@ namespace SparkleShare {
} }
public void SyncingCancelled ()
{
Program.Controller.StopFetcher ();
if (ChangePageEvent != null)
ChangePageEvent (PageType.Add);
}
public void FinishedPageCompleted () public void FinishedPageCompleted ()
{ {
this.previous_server = ""; this.previous_server = "";

View file

@ -23,6 +23,7 @@ using System.Text.RegularExpressions;
using System.Timers; using System.Timers;
using Gtk; using Gtk;
using Mono.Unix;
using SparkleLib; using SparkleLib;
namespace SparkleShare { namespace SparkleShare {
@ -41,7 +42,7 @@ namespace SparkleShare {
public SparkleSetupWindow () : base ("") public SparkleSetupWindow () : base ("")
{ {
Title = "SparkleShare Setup"; Title = Catalog.GetString ("SparkleShare Setup");
BorderWidth = 0; BorderWidth = 0;
IconName = "folder-sparkleshare"; IconName = "folder-sparkleshare";
Resizable = false; Resizable = false;
@ -70,17 +71,13 @@ namespace SparkleShare {
EventBox box = new EventBox (); EventBox box = new EventBox ();
Gdk.Color bg_color = new Gdk.Color (); Gdk.Color bg_color = new Gdk.Color ();
Gdk.Color.Parse ("#2e3336", ref bg_color); Gdk.Color.Parse ("#000", ref bg_color);
box.ModifyBg (StateType.Normal, bg_color); box.ModifyBg (StateType.Normal, bg_color);
string image_path = SparkleHelpers.CombineMore (Defines.DATAROOTDIR, "sparkleshare", Image side_splash = SparkleUIHelpers.GetImage ("side-splash.png");
"pixmaps", "side-splash.png"); side_splash.Yalign = 1;
Image side_splash = new Image (image_path) { box.Add (side_splash);
Yalign = 1
};
box.Add (side_splash);
HBox.PackStart (box, false, false, 0); HBox.PackStart (box, false, false, 0);
HBox.PackStart (VBox, true, true, 0); HBox.PackStart (VBox, true, true, 0);
@ -125,7 +122,7 @@ namespace SparkleShare {
layout_vertical.PackStart (description, false, false, 21); layout_vertical.PackStart (description, false, false, 21);
if (widget != null) if (widget != null)
layout_vertical.PackStart (widget, true, true, 21); layout_vertical.PackStart (widget, true, true, 0);
Wrapper.PackStart (layout_vertical, true, true, 0); Wrapper.PackStart (layout_vertical, true, true, 0);
ShowAll (); ShowAll ();
@ -148,9 +145,7 @@ namespace SparkleShare {
new public void ShowAll () new public void ShowAll ()
{ {
Present ();
Present ();
base.ShowAll (); base.ShowAll ();
} }

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
@ -9,6 +9,7 @@
<AssemblyName>SparkleShare</AssemblyName> <AssemblyName>SparkleShare</AssemblyName>
<SchemaVersion>2.0</SchemaVersion> <SchemaVersion>2.0</SchemaVersion>
<RootNamespace>SparkleShare</RootNamespace> <RootNamespace>SparkleShare</RootNamespace>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
@ -37,15 +38,9 @@
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="Mono.Posix" /> <Reference Include="Mono.Posix" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SparkleLib\SparkleLib.csproj">
<Project>{2C914413-B31C-4362-93C7-1AE34F09112A}</Project>
<Name>SparkleLib</Name>
</ProjectReference>
</ItemGroup>
<ProjectExtensions> <ProjectExtensions>
<MonoDevelop> <MonoDevelop>
<Properties InternalTargetFrameworkVersion="3.5"> <Properties>
<MonoDevelop.Autotools.MakefileInfo IntegrationEnabled="true" RelativeMakefileName="Makefile.am"> <MonoDevelop.Autotools.MakefileInfo IntegrationEnabled="true" RelativeMakefileName="Makefile.am">
<BuildFilesVar Sync="true" Name="SOURCES" /> <BuildFilesVar Sync="true" Name="SOURCES" />
<DeployFilesVar /> <DeployFilesVar />
@ -63,11 +58,10 @@
<Compile Include="SparkleBubblesController.cs" /> <Compile Include="SparkleBubblesController.cs" />
<Compile Include="SparkleController.cs" /> <Compile Include="SparkleController.cs" />
<Compile Include="SparkleEntry.cs" /> <Compile Include="SparkleEntry.cs" />
<Compile Include="SparkleLinController.cs" />
<Compile Include="SparkleSetup.cs" /> <Compile Include="SparkleSetup.cs" />
<Compile Include="SparkleSetupController.cs" /> <Compile Include="SparkleSetupController.cs" />
<Compile Include="SparkleSetupWindow.cs" /> <Compile Include="SparkleSetupWindow.cs" />
<Compile Include="SparkleShare.cs" /> <Compile Include="Program.cs" />
<Compile Include="SparkleSpinner.cs" /> <Compile Include="SparkleSpinner.cs" />
<Compile Include="SparkleStatusIcon.cs" /> <Compile Include="SparkleStatusIcon.cs" />
<Compile Include="SparkleStatusIconController.cs" /> <Compile Include="SparkleStatusIconController.cs" />
@ -77,5 +71,7 @@
<Compile Include="SparkleEventLog.cs" /> <Compile Include="SparkleEventLog.cs" />
<Compile Include="SparkleAboutController.cs" /> <Compile Include="SparkleAboutController.cs" />
<Compile Include="SparkleAbout.cs" /> <Compile Include="SparkleAbout.cs" />
<Compile Include="SparkleExtensions.cs" />
<Compile Include="SparkleControllerBase.cs" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View file

@ -1,20 +1,14 @@
 
Microsoft Visual Studio Solution File, Format Version 9.00 Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2005 # Visual Studio 2008
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SparkleShare", "SparkleShare.csproj", "{728483AA-E34B-4441-BF2C-C8BC2901E4E0}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SparkleShare", "SparkleShare.csproj", "{728483AA-E34B-4441-BF2C-C8BC2901E4E0}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SparkleLib", "..\SparkleLib\SparkleLib.csproj", "{2C914413-B31C-4362-93C7-1AE34F09112A}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU Release|Any CPU = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{2C914413-B31C-4362-93C7-1AE34F09112A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2C914413-B31C-4362-93C7-1AE34F09112A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2C914413-B31C-4362-93C7-1AE34F09112A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2C914413-B31C-4362-93C7-1AE34F09112A}.Release|Any CPU.Build.0 = Release|Any CPU
{728483AA-E34B-4441-BF2C-C8BC2901E4E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {728483AA-E34B-4441-BF2C-C8BC2901E4E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{728483AA-E34B-4441-BF2C-C8BC2901E4E0}.Debug|Any CPU.Build.0 = Debug|Any CPU {728483AA-E34B-4441-BF2C-C8BC2901E4E0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{728483AA-E34B-4441-BF2C-C8BC2901E4E0}.Release|Any CPU.ActiveCfg = Release|Any CPU {728483AA-E34B-4441-BF2C-C8BC2901E4E0}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -22,7 +16,5 @@ Global
EndGlobalSection EndGlobalSection
GlobalSection(MonoDevelopProperties) = preSolution GlobalSection(MonoDevelopProperties) = preSolution
StartupItem = SparkleShare.csproj StartupItem = SparkleShare.csproj
outputpath = ..\bin
name = SparkleShare
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

View file

@ -23,7 +23,7 @@ using System.Timers;
using AppIndicator; using AppIndicator;
#endif #endif
using Gtk; using Gtk;
using SparkleLib; using Mono.Unix;
namespace SparkleShare { namespace SparkleShare {
@ -31,6 +31,8 @@ namespace SparkleShare {
// user's notification area // user's notification area
public class SparkleStatusIcon { public class SparkleStatusIcon {
public SparkleStatusIconController Controller = new SparkleStatusIconController ();
private Timer Animation; private Timer Animation;
private Gdk.Pixbuf [] AnimationFrames; private Gdk.Pixbuf [] AnimationFrames;
private int FrameNumber; private int FrameNumber;
@ -46,14 +48,14 @@ namespace SparkleShare {
// Short alias for the translations // Short alias for the translations
public static string _ (string s) public static string _ (string s)
{ {
return s; return Catalog.GetString (s);
} }
public SparkleStatusIcon () public SparkleStatusIcon ()
{ {
AnimationFrames = CreateAnimationFrames (); AnimationFrames = CreateAnimationFrames ();
Animation = CreateAnimation (); Animation = CreateAnimation ();
#if HAVE_APP_INDICATOR #if HAVE_APP_INDICATOR
this.indicator = new ApplicationIndicator ("sparkleshare", this.indicator = new ApplicationIndicator ("sparkleshare",
@ -66,45 +68,63 @@ namespace SparkleShare {
this.status_icon.Activate += ShowMenu; // Primary mouse button click this.status_icon.Activate += ShowMenu; // Primary mouse button click
this.status_icon.PopupMenu += ShowMenu; // Secondary mouse button click this.status_icon.PopupMenu += ShowMenu; // Secondary mouse button click
this.status_icon.Pixbuf = AnimationFrames [0];
#endif #endif
SetNormalState (); if (Controller.Folders.Length == 0)
StateText = _("Welcome to SparkleShare!");
else
StateText = _("Up to date") + " — " + Controller.FolderSize;
CreateMenu (); CreateMenu ();
SparkleShare.Controller.FolderSizeChanged += delegate { Controller.UpdateMenuEvent += delegate (IconState state) {
Application.Invoke (delegate { Application.Invoke (delegate {
if (!Animation.Enabled) switch (state) {
SetNormalState (); case IconState.Idle:
UpdateMenu (); Animation.Stop ();
});
};
SparkleShare.Controller.FolderListChanged += delegate {
Application.Invoke (delegate {
SetNormalState ();
CreateMenu ();
});
};
SparkleShare.Controller.OnIdle += delegate { if (Controller.Folders.Length == 0)
Application.Invoke (delegate { StateText = _("Welcome to SparkleShare!");
SetNormalState (); else
UpdateMenu (); StateText = _("Up to date") + " — " + Controller.FolderSize;
});
};
SparkleShare.Controller.OnSyncing += delegate { #if HAVE_APP_INDICATOR
Application.Invoke (delegate { this.indicator.IconName = "process-syncing-sparkleshare-i";
SetAnimationState (); #else
UpdateMenu (); this.status_icon.Pixbuf = AnimationFrames [0];
}); #endif
};
SparkleShare.Controller.OnError += delegate { UpdateStateText ();
Application.Invoke (delegate { CreateMenu ();
SetNormalState (true);
UpdateMenu (); break;
case IconState.Syncing:
StateText = _("Syncing…");
UpdateStateText (); // TODO
if (!Animation.Enabled)
Animation.Start ();
break;
case IconState.Error:
StateText = _("Not everything is synced");
UpdateStateText ();
CreateMenu ();
#if HAVE_APP_INDICATOR
this.indicator.IconName = "sparkleshare-syncing-error";
#else
this.status_icon.Pixbuf = SparkleUIHelpers.GetIcon ("sparkleshare-syncing-error", 24);
#endif
break;
}
}); });
}; };
} }
@ -176,18 +196,18 @@ namespace SparkleShare {
}; };
folder_item.Activated += delegate { folder_item.Activated += delegate {
SparkleShare.Controller.OpenSparkleShareFolder (); Program.Controller.OpenSparkleShareFolder ();
}; };
Menu.Add (folder_item); Menu.Add (folder_item);
if (SparkleShare.Controller.Folders.Count > 0) { if (Program.Controller.Folders.Count > 0) {
// Creates a menu item for each repository with a link to their logs // Creates a menu item for each repository with a link to their logs
foreach (string folder_name in SparkleShare.Controller.Folders) { foreach (string folder_name in Program.Controller.Folders) {
Gdk.Pixbuf folder_icon; Gdk.Pixbuf folder_icon;
if (SparkleShare.Controller.UnsyncedFolders.Contains (folder_name)) { if (Program.Controller.UnsyncedFolders.Contains (folder_name)) {
folder_icon = IconTheme.Default.LoadIcon ("dialog-error", 16, folder_icon = IconTheme.Default.LoadIcon ("dialog-error", 16,
IconLookupFlags.GenericFallback); IconLookupFlags.GenericFallback);
@ -205,7 +225,7 @@ namespace SparkleShare {
} }
} else { } else {
MenuItem no_folders_item = new MenuItem (_("No Remote Folders Yet")) { MenuItem no_folders_item = new MenuItem (_("No projects yet")) {
Sensitive = false Sensitive = false
}; };
@ -215,9 +235,9 @@ namespace SparkleShare {
Menu.Add (new SeparatorMenuItem ()); Menu.Add (new SeparatorMenuItem ());
// Opens the wizard to add a new remote folder // Opens the wizard to add a new remote folder
MenuItem sync_item = new MenuItem (_("Add Remote Folder…")); MenuItem sync_item = new MenuItem (_("Add Project…"));
if (SparkleShare.Controller.FirstRun) if (Program.Controller.FirstRun)
sync_item.Sensitive = false; sync_item.Sensitive = false;
sync_item.Activated += delegate { sync_item.Activated += delegate {
@ -241,7 +261,7 @@ namespace SparkleShare {
MenuItem recent_events_item = new MenuItem (_("Show Recent Events")); MenuItem recent_events_item = new MenuItem (_("Show Recent Events"));
if (SparkleShare.Controller.Folders.Count < 1) if (Program.Controller.Folders.Count < 1)
recent_events_item.Sensitive = false; recent_events_item.Sensitive = false;
recent_events_item.Activated += delegate { recent_events_item.Activated += delegate {
@ -258,13 +278,13 @@ namespace SparkleShare {
MenuItem notify_item; MenuItem notify_item;
if (SparkleShare.Controller.NotificationsEnabled) if (Program.Controller.NotificationsEnabled)
notify_item = new MenuItem (_("Turn Notifications Off")); notify_item = new MenuItem (_("Turn Notifications Off"));
else else
notify_item = new MenuItem (_("Turn Notifications On")); notify_item = new MenuItem (_("Turn Notifications On"));
notify_item.Activated += delegate { notify_item.Activated += delegate {
SparkleShare.Controller.ToggleNotifications (); Program.Controller.ToggleNotifications ();
CreateMenu (); CreateMenu ();
}; };
@ -291,7 +311,7 @@ namespace SparkleShare {
MenuItem quit_item = new MenuItem (_("Quit")); MenuItem quit_item = new MenuItem (_("Quit"));
quit_item.Activated += delegate { quit_item.Activated += delegate {
SparkleShare.Controller.Quit (); Program.Controller.Quit ();
}; };
Menu.Add (quit_item); Menu.Add (quit_item);
@ -308,12 +328,12 @@ namespace SparkleShare {
private EventHandler OpenFolderDelegate (string name) private EventHandler OpenFolderDelegate (string name)
{ {
return delegate { return delegate {
SparkleShare.Controller.OpenSparkleShareFolder (name); Program.Controller.OpenSparkleShareFolder (name);
}; };
} }
public void UpdateMenu () public void UpdateStateText ()
{ {
((Menu.Children [0] as MenuItem).Child as Label).Text = StateText; ((Menu.Children [0] as MenuItem).Child as Label).Text = StateText;
Menu.ShowAll (); Menu.ShowAll ();
@ -323,11 +343,7 @@ namespace SparkleShare {
// Makes the menu visible // Makes the menu visible
private void ShowMenu (object o, EventArgs args) private void ShowMenu (object o, EventArgs args)
{ {
if ((SparkleBackend.Platform == PlatformID.Unix || Menu.Popup (null, null, SetPosition, 0, Global.CurrentEventTime);
SparkleBackend.Platform == PlatformID.MacOSX))
Menu.Popup (null, null, SetPosition, 0, Global.CurrentEventTime);
else
Menu.Popup (null, null, null, 0, Global.CurrentEventTime);
} }
@ -337,63 +353,6 @@ namespace SparkleShare {
StatusIcon.PositionMenu (menu, out x, out y, out push_in, this.status_icon.Handle); StatusIcon.PositionMenu (menu, out x, out y, out push_in, this.status_icon.Handle);
} }
#endif #endif
// The state when there's nothing going on
private void SetNormalState ()
{
SetNormalState (false);
}
// The state when there's nothing going on
private void SetNormalState (bool error)
{
Animation.Stop ();
if (SparkleShare.Controller.Folders.Count == 0) {
StateText = _("Welcome to SparkleShare!");
Application.Invoke (delegate {
#if HAVE_APP_INDICATOR
this.indicator.IconName = "process-syncing-sparkleshare-i";
#else
this.status_icon.Pixbuf = AnimationFrames [0];
#endif
});
} else {
if (error) {
StateText = _("Not everything is synced");
Application.Invoke (delegate {
#if HAVE_APP_INDICATOR
this.indicator.IconName = "sparkleshare-syncing-error";
#else
this.status_icon.Pixbuf = SparkleUIHelpers.GetIcon ("sparkleshare-syncing-error", 24);
#endif
});
} else {
StateText = _("Up to date") + " (" + SparkleShare.Controller.FolderSize + ")";
Application.Invoke (delegate {
#if HAVE_APP_INDICATOR
this.indicator.IconName = "process-syncing-sparkleshare-i";
#else
this.status_icon.Pixbuf = AnimationFrames [0];
#endif
});
}
}
}
// The state when animating
private void SetAnimationState ()
{
StateText = _("Syncing…");
if (!Animation.Enabled)
Animation.Start ();
}
} }

View file

@ -38,29 +38,29 @@ namespace SparkleShare {
public string [] Folders { public string [] Folders {
get { get {
return SparkleShare.Controller.Folders.ToArray (); return Program.Controller.Folders.ToArray ();
} }
} }
public string FolderSize { public string FolderSize {
get { get {
return SparkleShare.Controller.FolderSize; return Program.Controller.FolderSize;
} }
} }
public SparkleStatusIconController () public SparkleStatusIconController ()
{ {
SparkleShare.Controller.FolderSizeChanged += delegate { Program.Controller.FolderSizeChanged += delegate {
if (UpdateMenuEvent != null) if (UpdateMenuEvent != null)
UpdateMenuEvent (CurrentState); UpdateMenuEvent (CurrentState);
}; };
SparkleShare.Controller.FolderListChanged += delegate { Program.Controller.FolderListChanged += delegate {
if (UpdateMenuEvent != null) if (UpdateMenuEvent != null)
UpdateMenuEvent (CurrentState); UpdateMenuEvent (CurrentState);
}; };
SparkleShare.Controller.OnIdle += delegate { Program.Controller.OnIdle += delegate {
if (CurrentState != IconState.Error) if (CurrentState != IconState.Error)
CurrentState = IconState.Idle; CurrentState = IconState.Idle;
@ -68,14 +68,16 @@ namespace SparkleShare {
UpdateMenuEvent (CurrentState); UpdateMenuEvent (CurrentState);
}; };
SparkleShare.Controller.OnSyncing += delegate { Program.Controller.OnSyncing += delegate {
CurrentState = IconState.Syncing; CurrentState = IconState.Syncing;
// TODO up down both
if (UpdateMenuEvent != null) if (UpdateMenuEvent != null)
UpdateMenuEvent (IconState.Syncing); UpdateMenuEvent (IconState.Syncing);
}; };
SparkleShare.Controller.OnError += delegate { Program.Controller.OnError += delegate {
CurrentState = IconState.Error; CurrentState = IconState.Error;
if (UpdateMenuEvent != null) if (UpdateMenuEvent != null)

View file

@ -40,14 +40,20 @@ namespace SparkleShare {
public static Gdk.Pixbuf GetIcon (string name, int size) public static Gdk.Pixbuf GetIcon (string name, int size)
{ {
IconTheme icon_theme = new IconTheme (); IconTheme icon_theme = new IconTheme ();
icon_theme.AppendSearchPath (SparklePaths.SparkleIconPath);
icon_theme.AppendSearchPath (SparklePaths.SparkleLocalIconPath); icon_theme.AppendSearchPath (
Path.Combine (SparkleUI.AssetsPath, "icons"));
icon_theme.AppendSearchPath (
Path.Combine (SparkleConfig.ConfigPath, "icons"));
try { try {
return icon_theme.LoadIcon (name, size, IconLookupFlags.GenericFallback); return icon_theme.LoadIcon (name, size, IconLookupFlags.GenericFallback);
} catch { } catch {
try { try {
return icon_theme.LoadIcon ("gtk-missing-image", size, IconLookupFlags.GenericFallback); return icon_theme.LoadIcon ("gtk-missing-image", size, IconLookupFlags.GenericFallback);
} catch { } catch {
return null; return null;
} }
@ -55,6 +61,15 @@ namespace SparkleShare {
} }
public static Image GetImage (string name)
{
string image_path = SparkleHelpers.CombineMore (Defines.DATAROOTDIR, "sparkleshare",
"pixmaps", name);
return new Image (image_path);
}
// Converts a Gdk RGB color to a hex value. // Converts a Gdk RGB color to a hex value.
// Example: from "rgb:0,0,0" to "#000000" // Example: from "rgb:0,0,0" to "#000000"
public static string GdkColorToHex (Gdk.Color color) public static string GdkColorToHex (Gdk.Color color)

View file

@ -22,13 +22,16 @@ using System.IO;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
#if __MonoCS__
using Mono.Unix;
//using Mono.Unix.Native;
#endif
using SparkleLib; using SparkleLib;
using SparkleLib.Options; using SparkleLib.Options;
namespace SparkleShare { namespace SparkleShare {
// This is SparkleShare! // This is SparkleShare!
// http://blogs.msdn.com/b/ericlippert/archive/2010/03/09/do-not-name-a-class-the-same-as-its-namespace-part-one.aspx
public class Program { public class Program {
public static SparkleController Controller; public static SparkleController Controller;
@ -38,22 +41,18 @@ namespace SparkleShare {
// Short alias for the translations // Short alias for the translations
public static string _ (string s) public static string _ (string s)
{ {
#if __MonoCS__
return Catalog.GetString (s);
#else
return s; return s;
#endif
} }
#if !__MonoCS__
[STAThread] [STAThread]
#endif
public static void Main (string [] args) public static void Main (string [] args)
{ {
// Don't allow running as root on Linux or Mac
#if __MonoCS__
if (new Mono.Unix.UnixUserInfo (Mono.Unix.UnixEnvironment.UserName).UserId == 0) {
Console.WriteLine (_("Sorry, you can't run SparkleShare with these permissions."));
Console.WriteLine (_("Things would go utterly wrong."));
Environment.Exit (-1);
}
#endif
// Parse the command line options // Parse the command line options
bool show_help = false; bool show_help = false;
OptionSet option_set = new OptionSet () { OptionSet option_set = new OptionSet () {
@ -73,25 +72,10 @@ namespace SparkleShare {
if (show_help) if (show_help)
ShowHelp (option_set); ShowHelp (option_set);
// Load the right controller for the OS
string controller_name = "Lin";
switch (SparkleBackend.Platform) {
case PlatformID.Unix:
SetProcessName ("sparkleshare");
break;
case PlatformID.MacOSX:
controller_name = "Mac";
break;
case PlatformID.Win32NT:
controller_name = "Win";
break;
}
// Initialize the controller this way so that // Initialize the controller this way so that
// there aren't any exceptions in the OS specific UI's // there aren't any exceptions in the OS specific UI's
Controller = (SparkleController) Activator.CreateInstance ( Controller = new SparkleController ();
Type.GetType ("SparkleShare.Sparkle" + controller_name + "Controller"));
Controller.Initialize (); Controller.Initialize ();
if (Controller != null) { if (Controller != null) {

View file

@ -28,9 +28,9 @@ using CefSharp;
namespace SparkleShare { namespace SparkleShare {
public class SparkleWinController : SparkleController { public class SparkleController : SparkleControllerBase {
public SparkleWinController () : base () public SparkleController () : base ()
{ {
} }

View file

@ -71,6 +71,12 @@
<DesignTime>True</DesignTime> <DesignTime>True</DesignTime>
<DependentUpon>GlobalAssemblyInfo.tt</DependentUpon> <DependentUpon>GlobalAssemblyInfo.tt</DependentUpon>
</Compile> </Compile>
<Compile Include="..\SparkleControllerBase.cs">
<Link>SparkleControllerBase.cs</Link>
</Compile>
<Compile Include="..\SparkleExtensions.cs">
<Link>SparkleExtensions.cs</Link>
</Compile>
<Compile Include="ApplicationSchemeHandler.cs" /> <Compile Include="ApplicationSchemeHandler.cs" />
<Compile Include="AssemblyInfo.cs" /> <Compile Include="AssemblyInfo.cs" />
<Compile Include="controls\ExampleTextBox.cs"> <Compile Include="controls\ExampleTextBox.cs">
@ -104,8 +110,8 @@
</Compile> </Compile>
<Compile Include="..\SparkleSetupController.cs" /> <Compile Include="..\SparkleSetupController.cs" />
<Compile Include="..\SparkleUI.cs" /> <Compile Include="..\SparkleUI.cs" />
<Compile Include="..\SparkleController.cs" />
<Compile Include="..\SparkleAboutController.cs" /> <Compile Include="..\SparkleAboutController.cs" />
<Compile Include="SparkleController.cs" />
<Compile Include="SparkleEventLog.cs"> <Compile Include="SparkleEventLog.cs">
<SubType>Form</SubType> <SubType>Form</SubType>
</Compile> </Compile>
@ -121,7 +127,6 @@
<Compile Include="Program.cs" /> <Compile Include="Program.cs" />
<Compile Include="SparkleStatusIcon.cs" /> <Compile Include="SparkleStatusIcon.cs" />
<Compile Include="SparkleUIHelpers.cs" /> <Compile Include="SparkleUIHelpers.cs" />
<Compile Include="SparkleWinController.cs" />
<Compile Include="controls\TablessControl.cs"> <Compile Include="controls\TablessControl.cs">
<SubType>Component</SubType> <SubType>Component</SubType>
</Compile> </Compile>

View file

@ -1,5 +1,10 @@
#!/bin/bash #!/bin/bash
if [[ $UID -eq 0 ]]; then
echo "Cannot run as root. Things would go utterly wrong."
exit 1
fi
if [ "$XDG_RUNTIME_DIR" ]; then if [ "$XDG_RUNTIME_DIR" ]; then
pidfile=${XDG_RUNTIME_DIR}/sparkleshare.pid pidfile=${XDG_RUNTIME_DIR}/sparkleshare.pid
else else