Actually grab the repo name fro mthe entry in Add dialog
This commit is contained in:
parent
1e04bade71
commit
a55232f29d
13
AUTHORS
13
AUTHORS
|
@ -1,6 +1,11 @@
|
|||
Maintainer:
|
||||
Hylke Bons <hylkebons@gmail.com>
|
||||
|
||||
Artwork by:
|
||||
Lapo Calamandrei <calamandrei@gmail.com>
|
||||
Jakub Steiner <jimmac@novell.com>
|
||||
Hylke Bons <hylkebons@gmail.com>
|
||||
|
||||
|
||||
Contributions by:
|
||||
|
||||
Lapo Calamandrei <calamandrei@gmail.com>
|
||||
Garrett LeSage <garrett@novell.com>
|
||||
Andreas Nilsson <andreasn@gnome.org>
|
||||
Jakub Steiner <jimmac@novell.com>
|
||||
|
|
54
LICENSE
54
LICENSE
|
@ -619,57 +619,3 @@ Program, unless a warranty or assumption of liability accompanies a
|
|||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
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/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
|
||||
|
|
19
README
19
README
|
@ -1,18 +1,17 @@
|
|||
SparkleShare Version 0.0.12
|
||||
SparkleShare Version 0.0.14
|
||||
===========================
|
||||
|
||||
SparkleShare is a file sharing and collaboration tool inspired by Dropbox. It
|
||||
allows you to instantly sync with any Git repository you have access to.
|
||||
SparkleShare is a file sharing and collaboration tool inspired by Dropbox.
|
||||
|
||||
SparkleShare isn't just a piece of software, it's part of your workflow. It's
|
||||
designed to make sharing documents and collaboration easier, and to make peers
|
||||
aware of what you are doing. The user interface and features are made to
|
||||
support this goal. However, you may find SparkleShare useful for other kinds of
|
||||
purposes as well, like backing up files or monitoring your favourite project.
|
||||
SparkleShare is not made to be a graphical frontend for git or a backup tool
|
||||
|
||||
In contrast to the projects name, we will very likely
|
||||
refuse to implement your personal ponies. :)
|
||||
aware of what you are doing. It allows you to instantly sync with any Git
|
||||
repository you have access to. The user interface and features are made to
|
||||
support this goal. Though SparkleShare is not made to be a graphical frontend
|
||||
for git or a backup tool, it may be useful for other kinds of purposes as well,
|
||||
like backing up small files or monitoring your favourite project. In contrast
|
||||
to the projects name, we will very likely refuse to implement your personal
|
||||
ponies. :)
|
||||
|
||||
SparkleShare currently only works on Linux/GNOME.
|
||||
Windows and OSX ports are planned for the future.
|
||||
|
|
56
SparkleShare
Normal file
56
SparkleShare
Normal file
|
@ -0,0 +1,56 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Create a directory to save the pid to
|
||||
mkdir -p /tmp/sparkleshare/
|
||||
|
||||
if [[ "$1" == "start" ]]; then
|
||||
if [ -e "/tmp/sparkleshare/sparkleshare.pid" ]; then
|
||||
echo "SparkleShare is already running."
|
||||
else
|
||||
echo -n "Starting SparkleShare..."
|
||||
|
||||
# Start SparkleShare in the background and save the pid
|
||||
mono /usr/local/share/sparkleshare/SparkleShare.exe $2 &
|
||||
PID=$!
|
||||
echo $PID > /tmp/sparkleshare/sparkleshare.pid
|
||||
echo " Done."
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$1" == "stop" ]]; then
|
||||
if [ -e "/tmp/sparkleshare/sparkleshare.pid" ]; then
|
||||
echo -n "Stopping SparkleShare..."
|
||||
kill `cat /tmp/sparkleshare/sparkleshare.pid`
|
||||
rm -f /tmp/sparkleshare/sparkleshare.pid
|
||||
echo " Done."
|
||||
else
|
||||
echo "SparkleShare isn't running."
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$1" == "restart" ]]; then
|
||||
if [ -e "/tmp/sparkleshare/sparkleshare.pid" ]; then
|
||||
echo -n "Stopping SparkleShare..."
|
||||
kill `cat /tmp/sparkleshare/sparkleshare.pid`
|
||||
rm -f /tmp/sparkleshare/sparkleshare.pid
|
||||
echo " Done."
|
||||
else
|
||||
echo "SparkleShare isn't running."
|
||||
fi
|
||||
|
||||
if [ -e "/tmp/sparkleshare/sparkleshare.pid" ]; then
|
||||
echo "SparkleShare is already running."
|
||||
else
|
||||
echo -n "Starting SparkleShare..."
|
||||
|
||||
# Start SparkleShare in the background and save the pid
|
||||
mono /usr/local/share/sparkleshare/SparkleShare.exe $2 &
|
||||
PID=$!
|
||||
echo $PID > /tmp/sparkleshare/sparkleshare.pid
|
||||
echo " Done."
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$1" == "--help" ]]; then
|
||||
mono /usr/local/share/sparkleshare/SparkleShare.exe --help
|
||||
fi
|
|
@ -1,32 +0,0 @@
|
|||
// SparkleShare, an instant update workflow to Git.
|
||||
// Copyright (C) 2010 Hylke Bons <hylkebons@gmail.com>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
using Notifications;
|
||||
|
||||
namespace SparkleShare {
|
||||
|
||||
public class SparkleBubble : Notification {
|
||||
|
||||
public SparkleBubble (string Title, string Subtext) : base (Title, Subtext) {
|
||||
Timeout = 4500;
|
||||
Urgency = Urgency.Low;
|
||||
Show ();
|
||||
// StatusIcon = SparkleUI.NotificationIcon; // Doesn't work for some reason :(
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,174 +0,0 @@
|
|||
// SparkleShare, an instant update workflow to Git.
|
||||
// Copyright (C) 2010 Hylke Bons <hylkebons@gmail.com>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
using Gtk;
|
||||
using Mono.Unix;
|
||||
using SparkleShare;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
||||
namespace SparkleShare {
|
||||
|
||||
// A dialog where the user can enter a folder
|
||||
// name and url to sync changes with
|
||||
public class SparkleDialog : Window {
|
||||
|
||||
// Short alias for the translations
|
||||
public static string _ (string s) {
|
||||
return Catalog.GetString (s);
|
||||
}
|
||||
|
||||
private Button AddButton;
|
||||
private ComboBoxEntry RemoteUrlCombo;
|
||||
private Entry NameEntry;
|
||||
|
||||
public SparkleDialog () : base ("") {
|
||||
|
||||
BorderWidth = 6;
|
||||
IconName = "folder-sparkleshare";
|
||||
Modal = true;
|
||||
Resizable = false;
|
||||
SetPosition (WindowPosition.Center);
|
||||
Title = _("Add a Folder");
|
||||
|
||||
VBox VBox = new VBox (false, 0);
|
||||
|
||||
Label NameLabel = new Label (_("Folder Name: "));
|
||||
NameEntry = new Entry ();
|
||||
Label NameExample = new Label (_("<span size='small'><i>Example: ") +
|
||||
_("‘Project’.</i></span>"));
|
||||
NameExample.UseMarkup = true;
|
||||
NameExample.SetAlignment (0, 0);
|
||||
NameLabel.Xalign = 1;
|
||||
|
||||
Label RemoteUrlLabel = new Label (_("Remote address: "));
|
||||
|
||||
string [] DefaultUrls = new string [4] { "ssh://git@github.com",
|
||||
"ssh://git@git.gnome.org",
|
||||
"ssh://git@fedorahosted.org",
|
||||
"ssh://git@gitorious.org" };
|
||||
|
||||
RemoteUrlCombo = new ComboBoxEntry (DefaultUrls);
|
||||
|
||||
Label RemoteUrlExample = new Label (_("<span size='small'><i>Example: ") +
|
||||
_("‘ssh://git@github.com’.</i></span>"));
|
||||
RemoteUrlExample.UseMarkup = true;
|
||||
RemoteUrlExample.SetAlignment (0, 0);
|
||||
RemoteUrlLabel.Xalign = 1;
|
||||
|
||||
HButtonBox ButtonBox = new HButtonBox ();
|
||||
ButtonBox.Layout = ButtonBoxStyle.End;
|
||||
ButtonBox.Spacing = 6;
|
||||
ButtonBox.BorderWidth = 6;
|
||||
|
||||
AddButton = new Button (Stock.Add);
|
||||
Button CancelButton = new Button (Stock.Cancel);
|
||||
|
||||
CancelButton.Clicked += delegate {
|
||||
Destroy ();
|
||||
};
|
||||
|
||||
RemoteUrlCombo.Entry.Changed += CheckFields;
|
||||
NameEntry.Changed += CheckFields;
|
||||
|
||||
AddButton.Sensitive = false;
|
||||
AddButton.Clicked += CloneRepo;
|
||||
|
||||
ButtonBox.Add (CancelButton);
|
||||
ButtonBox.Add (AddButton);
|
||||
|
||||
Table Table = new Table(4, 2, false);
|
||||
Table.RowSpacing = 6;
|
||||
Table.BorderWidth = 6;
|
||||
Table.Attach (NameLabel, 0, 1, 0, 1);
|
||||
|
||||
Table.Attach (NameEntry, 1, 2, 0, 1);
|
||||
Table.Attach (NameExample, 1, 2, 1, 2);
|
||||
Table.Attach (RemoteUrlLabel, 0, 1, 3, 4);
|
||||
Table.Attach (RemoteUrlCombo, 1, 2, 3, 4);
|
||||
Table.Attach (RemoteUrlExample, 1, 2, 4, 5);
|
||||
|
||||
VBox.PackStart (Table, false, false, 0);
|
||||
VBox.PackStart (ButtonBox, false, false, 0);
|
||||
|
||||
Add (VBox);
|
||||
ShowAll ();
|
||||
|
||||
}
|
||||
|
||||
public void CloneRepo (object o, EventArgs args) {
|
||||
|
||||
Remove (Child);
|
||||
VBox Box = new VBox (false, 24);
|
||||
SparkleSpinner Spinner = new SparkleSpinner ();
|
||||
Label Label = new Label (_("Downloading files,\n") +
|
||||
_("this may take a while..."));
|
||||
Box.PackStart (Spinner, false, false, 0);
|
||||
Box.PackStart (Label, false, false, 0);
|
||||
BorderWidth = 30;
|
||||
Add (Box);
|
||||
|
||||
string RepoRemoteUrl = RemoteUrlCombo.Entry.Text;
|
||||
string RepoName = NameEntry.Text;
|
||||
|
||||
Process Process = new Process();
|
||||
Process.EnableRaisingEvents = true;
|
||||
Process.StartInfo.RedirectStandardOutput = true;
|
||||
Process.StartInfo.UseShellExecute = false;
|
||||
Process.StartInfo.FileName = "git";
|
||||
Process.StartInfo.WorkingDirectory =
|
||||
SparklePaths.SparkleTmpPath;
|
||||
|
||||
Process.StartInfo.Arguments =
|
||||
"clone " + SparkleHelpers.CombineMore (RepoRemoteUrl, RepoName)
|
||||
.Substring (2);
|
||||
|
||||
Process.Start ();
|
||||
Process.Exited += delegate {
|
||||
Directory.Move (
|
||||
SparkleHelpers.CombineMore (SparklePaths.SparkleTmpPath,
|
||||
RepoName),
|
||||
SparkleHelpers.CombineMore (SparklePaths.SparklePath,
|
||||
RepoName)
|
||||
);
|
||||
|
||||
// Enable notifications and synchronisation by default
|
||||
File.Create (SparkleHelpers.CombineMore (SparklePaths.SparklePath,
|
||||
RepoName, ".git",
|
||||
"sparkleshare.notify"));
|
||||
|
||||
File.Create (SparkleHelpers.CombineMore (SparklePaths.SparklePath,
|
||||
RepoName, ".git",
|
||||
"sparkleshare.sync"));
|
||||
Destroy ();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// Enables the Add button when the fields are
|
||||
// filled in correctly
|
||||
public void CheckFields (object o, EventArgs args) {
|
||||
if (SparkleHelpers.IsGitUrl (RemoteUrlCombo.Entry.Text)
|
||||
&& NameEntry.Text.Length > 0)
|
||||
AddButton.Sensitive = true;
|
||||
else
|
||||
AddButton.Sensitive = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,105 +0,0 @@
|
|||
// SparkleShare, an instant update workflow to Git.
|
||||
// Copyright (C) 2010 Hylke Bons <hylkebons@gmail.com>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
using Gtk;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace SparkleShare {
|
||||
|
||||
public static class SparkleHelpers {
|
||||
|
||||
public static Gdk.Pixbuf GetAvatar (string Email, int Size) {
|
||||
|
||||
string AvatarPath = Path.Combine (SparklePaths.SparkleAvatarPath,
|
||||
Size + "x" + Size);
|
||||
|
||||
if (!Directory.Exists (AvatarPath)) {
|
||||
Directory.CreateDirectory (AvatarPath);
|
||||
Console.WriteLine ("[Config] Created '" + AvatarPath + "'");
|
||||
}
|
||||
|
||||
string AvatarFilePath = AvatarPath + Email;
|
||||
|
||||
if (File.Exists (AvatarFilePath))
|
||||
return new Gdk.Pixbuf (AvatarFilePath);
|
||||
else {
|
||||
|
||||
// Let's try to get the person's gravatar for next time
|
||||
WebClient WebClient = new WebClient ();
|
||||
Uri GravatarUri = new Uri ("http://www.gravatar.com/avatar/" +
|
||||
GetMD5 (Email) + ".jpg?s=" + Size + "&d=404");
|
||||
|
||||
string TmpFile = SparklePaths.SparkleTmpPath + Email + Size;
|
||||
|
||||
if (!File.Exists (TmpFile)) {
|
||||
|
||||
WebClient.DownloadFileAsync (GravatarUri, TmpFile);
|
||||
WebClient.DownloadFileCompleted += delegate {
|
||||
File.Delete (AvatarPath + Email);
|
||||
FileInfo TmpFileInfo = new FileInfo (TmpFile);
|
||||
if (TmpFileInfo.Length > 255)
|
||||
File.Move (TmpFile, AvatarPath + Email);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
if (File.Exists (AvatarPath + Email))
|
||||
return new Gdk.Pixbuf (AvatarPath + Email);
|
||||
else
|
||||
return GetIcon ("avatar-default", Size);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Creates an MD5 hash
|
||||
public static string GetMD5 (string s) {
|
||||
MD5 md5 = new MD5CryptoServiceProvider ();
|
||||
Byte[] Bytes = ASCIIEncoding.Default.GetBytes (s);
|
||||
Byte[] EncodedBytes = md5.ComputeHash (Bytes);
|
||||
return BitConverter.ToString(EncodedBytes).ToLower ().Replace ("-", "");
|
||||
}
|
||||
|
||||
// Makes it possible to combine more than
|
||||
// two paths at once.
|
||||
public static string CombineMore (params string [] Parts) {
|
||||
string NewPath = " ";
|
||||
foreach (string Part in Parts)
|
||||
NewPath = Path.Combine (NewPath, Part);
|
||||
return NewPath;
|
||||
}
|
||||
|
||||
public static IconTheme SparkleTheme = new IconTheme ();
|
||||
|
||||
// Looks up an icon from the system's theme
|
||||
public static Gdk.Pixbuf GetIcon (string Name, int Size) {
|
||||
SparkleTheme.AppendSearchPath (SparklePaths.SparkleInstallPath);
|
||||
return SparkleTheme.LoadIcon (Name, Size,
|
||||
IconLookupFlags.GenericFallback);
|
||||
}
|
||||
|
||||
public static bool IsGitUrl (string Url) {
|
||||
return Regex.Match (Url, @"[a-z]+://(.)+").Success;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
// SparkleShare, an instant update workflow to Git.
|
||||
// Copyright (C) 2010 Hylke Bons <hylkebons@gmail.com>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace SparkleShare {
|
||||
|
||||
public static class SparklePaths {
|
||||
|
||||
public static string SparkleTmpPath = "/tmp/sparkleshare";
|
||||
|
||||
public static string HomePath =
|
||||
Environment.GetEnvironmentVariable("HOME");
|
||||
|
||||
public static string SparklePath = Path.Combine (HomePath ,"SparkleShare");
|
||||
|
||||
public static string SparkleConfigPath =
|
||||
SparkleHelpers.CombineMore (HomePath, ".config", "sparkleshare");
|
||||
|
||||
public static string SparkleInstallPath =
|
||||
SparkleHelpers.CombineMore ("usr", "share", "sparkleshare",
|
||||
"icons", "hicolor");
|
||||
|
||||
public static string SparkleAvatarPath =
|
||||
Path.Combine (SparkleConfigPath, "avatars");
|
||||
|
||||
public static string SparkleIconPath = "/usr/share/icons/hicolor";
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
// SparkleShare, an instant update workflow to Git.
|
||||
// Copyright (C) 2010 Hylke Bons <hylkebons@gmail.com>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
|
||||
namespace SparkleShare {
|
||||
|
||||
public static class SparklePlatform {
|
||||
|
||||
// Detect OSX, Windows, GNOME or KDE here
|
||||
public static string Name = "GNOME";
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,403 +0,0 @@
|
|||
// SparkleShare, an instant update workflow to Git.
|
||||
// Copyright (C) 2010 Hylke Bons <hylkebons@gmail.com>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
using Gtk;
|
||||
using SparkleShare;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Timers;
|
||||
|
||||
namespace SparkleShare {
|
||||
|
||||
// SparkleRepo class holds repository information and timers
|
||||
public class SparkleRepo {
|
||||
|
||||
private Process Process;
|
||||
private Timer FetchTimer;
|
||||
private Timer BufferTimer;
|
||||
private FileSystemWatcher Watcher;
|
||||
|
||||
public string Name;
|
||||
public string Domain;
|
||||
public string LocalPath;
|
||||
public string RemoteOriginUrl;
|
||||
public string CurrentHash;
|
||||
|
||||
public string UserEmail;
|
||||
public string UserName;
|
||||
|
||||
public SparkleRepo (string RepoPath) {
|
||||
|
||||
Process = new Process();
|
||||
Process.EnableRaisingEvents = false;
|
||||
Process.StartInfo.RedirectStandardOutput = true;
|
||||
Process.StartInfo.UseShellExecute = false;
|
||||
|
||||
// Get the repository's path, example: "/home/user/SparkleShare/repo"
|
||||
LocalPath = RepoPath;
|
||||
Process.StartInfo.WorkingDirectory = LocalPath;
|
||||
|
||||
// Get user.name, example: "User Name"
|
||||
UserName = "Anonymous";
|
||||
Process.StartInfo.FileName = "git";
|
||||
Process.StartInfo.Arguments = "config --get user.name";
|
||||
Process.Start();
|
||||
UserName = Process.StandardOutput.ReadToEnd().Trim ();
|
||||
|
||||
// Get user.email, example: "user@github.com"
|
||||
UserEmail = "not.set@git-scm.com";
|
||||
Process.StartInfo.FileName = "git";
|
||||
Process.StartInfo.Arguments = "config --get user.email";
|
||||
Process.Start();
|
||||
UserEmail = Process.StandardOutput.ReadToEnd().Trim ();
|
||||
|
||||
// Get remote.origin.url, example: "ssh://git@github.com/user/repo"
|
||||
Process.StartInfo.FileName = "git";
|
||||
Process.StartInfo.Arguments = "config --get remote.origin.url";
|
||||
Process.Start();
|
||||
RemoteOriginUrl = Process.StandardOutput.ReadToEnd().Trim ();
|
||||
|
||||
// Get the repository name, example: "Project"
|
||||
Name = Path.GetFileName (LocalPath);
|
||||
|
||||
// Get the domain, example: "github.com"
|
||||
Domain = RemoteOriginUrl;
|
||||
Domain = Domain.Substring (Domain.IndexOf ("@") + 1);
|
||||
if (Domain.IndexOf (":") > -1)
|
||||
Domain = Domain.Substring (0, Domain.IndexOf (":"));
|
||||
else
|
||||
Domain = Domain.Substring (0, Domain.IndexOf ("/"));
|
||||
|
||||
// Get hash of the current commit
|
||||
Process.StartInfo.FileName = "git";
|
||||
Process.StartInfo.Arguments = "rev-list --max-count=1 HEAD";
|
||||
Process.Start();
|
||||
CurrentHash = Process.StandardOutput.ReadToEnd().Trim ();
|
||||
|
||||
// Watch the repository's folder
|
||||
Watcher = new FileSystemWatcher (LocalPath);
|
||||
Watcher.IncludeSubdirectories = true;
|
||||
Watcher.EnableRaisingEvents = true;
|
||||
Watcher.Filter = "*";
|
||||
Watcher.Changed += new FileSystemEventHandler(OnFileActivity);
|
||||
Watcher.Created += new FileSystemEventHandler(OnFileActivity);
|
||||
Watcher.Deleted += new FileSystemEventHandler(OnFileActivity);
|
||||
|
||||
// Fetch remote changes every 20 seconds
|
||||
FetchTimer = new Timer ();
|
||||
FetchTimer.Interval = 17500;
|
||||
FetchTimer.Elapsed += delegate {
|
||||
Fetch ();
|
||||
};
|
||||
|
||||
FetchTimer.Start();
|
||||
BufferTimer = new Timer ();
|
||||
|
||||
// Add everything that changed
|
||||
// since SparkleShare was stopped
|
||||
Add ();
|
||||
Console.WriteLine ("[Git][" + Name + "] Nothing going on...");
|
||||
|
||||
}
|
||||
|
||||
// Starts a time buffer when something changes
|
||||
public void OnFileActivity (object o, FileSystemEventArgs args) {
|
||||
WatcherChangeTypes wct = args.ChangeType;
|
||||
if (!ShouldIgnore (args.Name)) {
|
||||
Console.WriteLine ("[Event][" + Name + "] " + wct.ToString() +
|
||||
" '" + args.Name + "'");
|
||||
StartBufferTimer ();
|
||||
}
|
||||
}
|
||||
|
||||
// A buffer that will fetch changes after
|
||||
// file activity has settles down
|
||||
public void StartBufferTimer () {
|
||||
|
||||
FetchTimer.Stop ();
|
||||
int Interval = 4000;
|
||||
if (!BufferTimer.Enabled) {
|
||||
|
||||
// Delay for a few seconds to see if more files change
|
||||
BufferTimer.Interval = Interval;
|
||||
BufferTimer.Elapsed += delegate (object o, ElapsedEventArgs args) {
|
||||
Console.WriteLine ("[Buffer][" + Name + "] Done waiting.");
|
||||
Add ();
|
||||
};
|
||||
Console.WriteLine ("[Buffer][" + Name + "] " +
|
||||
"Waiting for more changes...");
|
||||
|
||||
BufferTimer.Start();
|
||||
|
||||
} else {
|
||||
|
||||
// Extend the delay when something changes
|
||||
BufferTimer.Close ();
|
||||
BufferTimer = new Timer ();
|
||||
BufferTimer.Interval = Interval;
|
||||
BufferTimer.Elapsed += delegate (object o, ElapsedEventArgs args) {
|
||||
Console.WriteLine ("[Buffer][" + Name + "] Done waiting.");
|
||||
Add ();
|
||||
};
|
||||
FetchTimer.Start ();
|
||||
|
||||
BufferTimer.Start();
|
||||
Console.WriteLine ("[Buffer][" + Name + "] " +
|
||||
"Waiting for more changes...");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Clones a remote repo
|
||||
public void Clone () {
|
||||
Process.StartInfo.Arguments = "clone " + RemoteOriginUrl;
|
||||
Process.Start();
|
||||
|
||||
// Add a gitignore file
|
||||
TextWriter Writer = new StreamWriter(LocalPath + ".gitignore");
|
||||
Writer.WriteLine("*~"); // Ignore gedit swap files
|
||||
Writer.WriteLine(".*.sw?"); // Ignore vi swap files
|
||||
Writer.Close();
|
||||
}
|
||||
|
||||
// Stages the made changes
|
||||
public void Add () {
|
||||
BufferTimer.Stop ();
|
||||
Console.WriteLine ("[Git][" + Name + "] Staging changes...");
|
||||
Process.StartInfo.Arguments = "add --all";
|
||||
Process.Start();
|
||||
Process.WaitForExit ();
|
||||
Console.WriteLine ("[Git][" + Name + "] Changes staged.");
|
||||
// SparkleUI.NotificationIcon.SetSyncingState ();
|
||||
string Message = FormatCommitMessage ();
|
||||
if (!Message.Equals ("")) {
|
||||
Commit (Message);
|
||||
Push ();
|
||||
Fetch ();
|
||||
// Push again in case of a conflict
|
||||
Push ();
|
||||
}
|
||||
}
|
||||
|
||||
// Commits the made changes
|
||||
public void Commit (string Message) {
|
||||
Console.WriteLine ("[Commit][" + Name + "] " + Message);
|
||||
Console.WriteLine ("[Git][" + Name + "] Commiting changes...");
|
||||
Process.StartInfo.Arguments = "commit -m \"" + Message + "\"";
|
||||
Process.Start();
|
||||
Process.WaitForExit ();
|
||||
Console.WriteLine ("[Git][" + Name + "] Changes commited.");
|
||||
}
|
||||
|
||||
// Fetches changes from the remote repo
|
||||
public void Fetch () {
|
||||
FetchTimer.Stop ();
|
||||
// SparkleUI.NotificationIcon.SetSyncingState ();
|
||||
Console.WriteLine ("[Git][" + Name + "] Fetching changes... ");
|
||||
Process.StartInfo.Arguments = "fetch -v";
|
||||
Process.Start();
|
||||
string Output = Process.StandardOutput.ReadToEnd().Trim (); // TODO: This doesn't work :(
|
||||
Process.WaitForExit ();
|
||||
Console.WriteLine ("[Git][" + Name + "] Changes fetched.");
|
||||
if (!Output.Contains ("up to date"))
|
||||
Merge ();
|
||||
// SparkleUI.NotificationIcon.SetIdleState ();
|
||||
FetchTimer.Start ();
|
||||
}
|
||||
|
||||
// Merges the fetched changes
|
||||
public void Merge () {
|
||||
// Watcher.EnableRaisingEvents = false;
|
||||
Console.WriteLine ("[Git][" + Name + "] Merging fetched changes... ");
|
||||
Process.StartInfo.Arguments = "merge origin/master";
|
||||
Process.Start();
|
||||
Process.WaitForExit ();
|
||||
Console.WriteLine ("[Git][" + Name + "] Changes merged.");
|
||||
string Output = Process.StandardOutput.ReadToEnd().Trim ();
|
||||
// Show notification if there are updates
|
||||
if (!Output.Equals ("Already up-to-date.")) {
|
||||
|
||||
// Get the last committer e-mail
|
||||
Process.StartInfo.Arguments = "log --format=\"%ae\" -1";
|
||||
Process.Start();
|
||||
string LastCommitEmail = Process.StandardOutput.ReadToEnd().Trim ();
|
||||
|
||||
// Get the last commit message
|
||||
Process.StartInfo.Arguments = "log --format=\"%s\" -1";
|
||||
Process.Start();
|
||||
string LastCommitMessage = Process.StandardOutput.ReadToEnd().Trim ();
|
||||
|
||||
// Get the last commiter
|
||||
Process.StartInfo.Arguments = "log --format=\"%an\" -1";
|
||||
Process.Start();
|
||||
string LastCommitUserName = Process.StandardOutput.ReadToEnd().Trim ();
|
||||
|
||||
string NotifySettingFile =
|
||||
SparkleHelpers.CombineMore (SparklePaths.SparkleConfigPath,
|
||||
"sparkleshare.notify");
|
||||
|
||||
if (File.Exists (NotifySettingFile))
|
||||
ShowEventBubble (LastCommitUserName + " " + LastCommitMessage,
|
||||
SparkleHelpers.GetAvatar (LastCommitEmail, 48),
|
||||
true);
|
||||
|
||||
}
|
||||
|
||||
// Watcher.EnableRaisingEvents = true;
|
||||
Console.WriteLine ("[Git][" + Name + "] Nothing going on... ");
|
||||
|
||||
}
|
||||
|
||||
// Pushes the changes to the remote repo
|
||||
public void Push () {
|
||||
Console.WriteLine ("[Git][" + Name + "] Pushing changes...");
|
||||
Process.StartInfo.Arguments = "push";
|
||||
Process.Start();
|
||||
Process.WaitForExit ();
|
||||
Console.WriteLine ("[Git][" + Name + "] Changes pushed.");
|
||||
// SparkleUI.NotificationIcon.SetIdleState ();
|
||||
}
|
||||
|
||||
// Ignores Repos, dotfiles, swap files and the like.
|
||||
public bool ShouldIgnore (string FileName) {
|
||||
if (FileName.Substring (0, 1).Equals (".") ||
|
||||
FileName.Contains (".lock") ||
|
||||
FileName.Contains (".git") ||
|
||||
FileName.Contains ("/.") ||
|
||||
Directory.Exists (LocalPath + FileName))
|
||||
return true; // Yes, ignore it.
|
||||
else if (FileName.Length > 3 &&
|
||||
FileName.Substring (FileName.Length - 4).Equals (".swp"))
|
||||
return true;
|
||||
else return false;
|
||||
}
|
||||
|
||||
// Creates a pretty commit message based on what has changed
|
||||
public string FormatCommitMessage () {
|
||||
|
||||
bool DoneAddCommit = false;
|
||||
bool DoneEditCommit = false;
|
||||
bool DoneRenameCommit = false;
|
||||
bool DoneDeleteCommit = false;
|
||||
int FilesAdded = 0;
|
||||
int FilesEdited = 0;
|
||||
int FilesRenamed = 0;
|
||||
int FilesDeleted = 0;
|
||||
|
||||
Process.StartInfo.Arguments = "status";
|
||||
Process.Start();
|
||||
string Output = Process.StandardOutput.ReadToEnd();
|
||||
|
||||
foreach (string Line in Regex.Split (Output, "\n")) {
|
||||
if (Line.IndexOf ("new file:") > -1)
|
||||
FilesAdded++;
|
||||
if (Line.IndexOf ("modified:") > -1)
|
||||
FilesEdited++;
|
||||
if (Line.IndexOf ("renamed:") > -1)
|
||||
FilesRenamed++;
|
||||
if (Line.IndexOf ("deleted:") > -1)
|
||||
FilesDeleted++;
|
||||
}
|
||||
|
||||
foreach (string Line in Regex.Split (Output, "\n")) {
|
||||
|
||||
// Format message for when files are added,
|
||||
// example: "added 'file' and 3 more."
|
||||
if (Line.IndexOf ("new file:") > -1 && !DoneAddCommit) {
|
||||
DoneAddCommit = true;
|
||||
if (FilesAdded > 1)
|
||||
return "added ‘" +
|
||||
Line.Replace ("#\tnew file:", "").Trim () +
|
||||
"’ and " + (FilesAdded - 1) + " more.";
|
||||
else
|
||||
return "added ‘" +
|
||||
Line.Replace ("#\tnew file:", "").Trim () + "’.";
|
||||
}
|
||||
|
||||
// Format message for when files are edited,
|
||||
// example: "edited 'file'."
|
||||
if (Line.IndexOf ("modified:") > -1 && !DoneEditCommit) {
|
||||
DoneEditCommit = true;
|
||||
if (FilesEdited > 1)
|
||||
return "edited ‘" +
|
||||
Line.Replace ("#\tmodified:", "").Trim () +
|
||||
"’ and " + (FilesEdited - 1) + " more.";
|
||||
else
|
||||
return "edited ‘" +
|
||||
Line.Replace ("#\tmodified:", "").Trim () + "’.";
|
||||
}
|
||||
|
||||
// Format message for when files are edited,
|
||||
// example: "deleted 'file'."
|
||||
if (Line.IndexOf ("deleted:") > -1 && !DoneDeleteCommit) {
|
||||
DoneDeleteCommit = true;
|
||||
if (FilesDeleted > 1)
|
||||
return "deleted ‘" +
|
||||
Line.Replace ("#\tdeleted:", "").Trim () +
|
||||
"’ and " + (FilesDeleted - 1) + " more.";
|
||||
else
|
||||
return "deleted ‘" +
|
||||
Line.Replace ("#\tdeleted:", "").Trim () + "’.";
|
||||
}
|
||||
|
||||
// Format message for when files are renamed,
|
||||
// example: "renamed 'file' to 'new name'."
|
||||
if (Line.IndexOf ("renamed:") > -1 && !DoneRenameCommit) {
|
||||
DoneDeleteCommit = true;
|
||||
if (FilesRenamed > 1)
|
||||
return "renamed ‘" +
|
||||
Line.Replace ("#\trenamed:", "").Trim ().Replace
|
||||
(" -> ", "’ to ‘") + "’ and " + (FilesDeleted - 1) +
|
||||
" more.";
|
||||
else
|
||||
return "renamed ‘" +
|
||||
Line.Replace ("#\trenamed:", "").Trim ().Replace
|
||||
(" -> ", "’ to ‘") + "’.";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Nothing happened:
|
||||
return "";
|
||||
|
||||
}
|
||||
|
||||
// Shows a notification with text and image
|
||||
public void ShowEventBubble (string Title,
|
||||
Gdk.Pixbuf Avatar,
|
||||
bool ShowButtons) {
|
||||
|
||||
SparkleBubble StuffChangedBubble = new SparkleBubble (Title, "");
|
||||
StuffChangedBubble.Icon = Avatar;
|
||||
|
||||
// Add a button to open the folder where the changed file is
|
||||
if (ShowButtons)
|
||||
StuffChangedBubble.AddAction ("", "Open Folder",
|
||||
delegate {
|
||||
Process.StartInfo.FileName = "xdg-open";
|
||||
Process.StartInfo.Arguments = LocalPath;
|
||||
Process.Start();
|
||||
Process.StartInfo.FileName = "git";
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,105 +0,0 @@
|
|||
// SparkleShare, an instant update workflow to Git.
|
||||
// Copyright (C) 2010 Hylke Bons <hylkebons@gmail.com>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
using Gtk;
|
||||
using Mono.Unix;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace SparkleShare {
|
||||
|
||||
// This is SparkleShare!
|
||||
public class SparkleShare {
|
||||
|
||||
// Short alias for the translations
|
||||
public static string _ (string s) {
|
||||
return Catalog.GetString (s);
|
||||
}
|
||||
|
||||
public static SparkleRepo [] Repositories;
|
||||
public static SparkleUI SparkleUI;
|
||||
|
||||
public static void Main (string [] args) {
|
||||
|
||||
// Use translations
|
||||
Catalog.Init ("i18n", "locale");
|
||||
|
||||
// Check if git is installed
|
||||
Process Process = new Process();
|
||||
Process.StartInfo.FileName = "git";
|
||||
Process.StartInfo.RedirectStandardOutput = true;
|
||||
Process.StartInfo.UseShellExecute = false;
|
||||
Process.Start();
|
||||
|
||||
if (Process.StandardOutput.ReadToEnd().IndexOf ("version") == -1) {
|
||||
Console.WriteLine (_("Git wasn't found."));
|
||||
Console.WriteLine (_("You can get Git from http://git-scm.com/."));
|
||||
Environment.Exit (0);
|
||||
}
|
||||
|
||||
// Don't allow running as root
|
||||
Process.StartInfo.FileName = "whoami";
|
||||
Process.Start();
|
||||
if (Process.StandardOutput.ReadToEnd().Trim ().Equals ("root")) {
|
||||
Console.WriteLine (_("Sorry, you can't run SparkleShare with these permissions."));
|
||||
Console.WriteLine (_("Things will go utterly wrong."));
|
||||
Environment.Exit (0);
|
||||
}
|
||||
|
||||
// Parse the command line arguments
|
||||
bool HideUI = false;
|
||||
if (args.Length > 0) {
|
||||
foreach (string Argument in args) {
|
||||
if (Argument.Equals ("--disable-gui") || Argument.Equals ("-d"))
|
||||
HideUI = true;
|
||||
if (Argument.Equals ("--help") || Argument.Equals ("-h")) {
|
||||
ShowHelp ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Gtk.Application.Init ();
|
||||
|
||||
SparkleUI = new SparkleUI (HideUI);
|
||||
|
||||
// The main loop
|
||||
Gtk.Application.Run ();
|
||||
|
||||
}
|
||||
|
||||
// Prints the help output
|
||||
public static void ShowHelp () {
|
||||
Console.WriteLine (_("SparkleShare Copyright (C) 2010 Hylke Bons"));
|
||||
Console.WriteLine (" ");
|
||||
Console.WriteLine (_("This program comes with ABSOLUTELY NO WARRANTY."));
|
||||
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 syncs the ~/SparkleShare folder with remote repositories."));
|
||||
Console.WriteLine (" ");
|
||||
Console.WriteLine (_("Usage: sparkleshare [start|stop|restart] [OPTION]..."));
|
||||
Console.WriteLine (_("Sync SparkleShare folder with remote repositories."));
|
||||
Console.WriteLine (" ");
|
||||
Console.WriteLine (_("Arguments:"));
|
||||
Console.WriteLine (_("\t -d, --disable-gui\tDon't show the notification icon."));
|
||||
Console.WriteLine (_("\t -h, --help\t\tDisplay this help text."));
|
||||
Console.WriteLine (" ");
|
||||
Environment.Exit (0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>8.0.50727</ProductVersion>
|
||||
<ProjectGuid>{728483AA-E34B-4441-BF2C-C8BC2901E4E0}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AssemblyName>SparkleShare</AssemblyName>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<RootNamespace>SparkleShare</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug</OutputPath>
|
||||
<DefineConstants>DEBUG</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>none</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Release</OutputPath>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<ItemGroup>
|
||||
<Reference Include="gtk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
|
||||
<Reference Include="notify-sharp, Version=0.4.0.0, Culture=neutral, PublicKeyToken=2df29c54e245917a" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="Mono.Posix" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="SparkleBubble.cs" />
|
||||
<Compile Include="SparkleDialog.cs" />
|
||||
<Compile Include="SparkleHelpers.cs" />
|
||||
<Compile Include="SparklePaths.cs" />
|
||||
<Compile Include="SparklePlatform.cs" />
|
||||
<Compile Include="SparkleRepo.cs" />
|
||||
<Compile Include="SparkleShare.cs" />
|
||||
<Compile Include="SparkleSpinner.cs" />
|
||||
<Compile Include="SparkleStatusIcon.cs" />
|
||||
<Compile Include="SparkleUI.cs" />
|
||||
<Compile Include="SparkleWindow.cs" />
|
||||
</ItemGroup>
|
||||
</Project>
|
Binary file not shown.
|
@ -1,91 +0,0 @@
|
|||
// SparkleShare, an instant update workflow to Git.
|
||||
// Copyright (C) 2010 Hylke Bons <hylkebons@gmail.com>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
using Gtk;
|
||||
using System.Timers;
|
||||
|
||||
namespace SparkleShare {
|
||||
|
||||
// This is a close implementation of GtkSpinner
|
||||
public class SparkleSpinner : Image {
|
||||
|
||||
public bool Active;
|
||||
|
||||
private Gdk.Pixbuf [] Images;
|
||||
private Timer Timer;
|
||||
private int CycleDuration;
|
||||
private int CurrentStep;
|
||||
private int NumSteps;
|
||||
private int Size;
|
||||
|
||||
public SparkleSpinner () : base () {
|
||||
|
||||
CycleDuration = 750;
|
||||
CurrentStep = 0;
|
||||
Size = 48;
|
||||
|
||||
Gdk.Pixbuf SpinnerGallery = SparkleHelpers.GetIcon ("process-working",
|
||||
Size);
|
||||
|
||||
int FramesInWidth = SpinnerGallery.Width / Size;
|
||||
int FramesInHeight = SpinnerGallery.Height / Size;
|
||||
NumSteps = FramesInWidth * FramesInHeight;
|
||||
Images = new Gdk.Pixbuf [NumSteps - 1];
|
||||
|
||||
int i = 0;
|
||||
for (int y = 0; y < FramesInHeight; y++) {
|
||||
for (int x = 0; x < FramesInWidth; x++) {
|
||||
if (!(y == 0 && x == 0)) {
|
||||
Images [i] = new Gdk.Pixbuf (SpinnerGallery,
|
||||
x * Size, y * Size, Size, Size);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Timer = new Timer ();
|
||||
Timer.Interval = CycleDuration / NumSteps;
|
||||
Timer.Elapsed += delegate { NextImage (); };
|
||||
Start ();
|
||||
|
||||
}
|
||||
|
||||
private void NextImage () {
|
||||
if (CurrentStep < NumSteps)
|
||||
CurrentStep++;
|
||||
else
|
||||
CurrentStep = 0;
|
||||
Pixbuf = Images [CurrentStep];
|
||||
}
|
||||
|
||||
public bool IsActive () {
|
||||
return Active;
|
||||
}
|
||||
|
||||
public void Start () {
|
||||
CurrentStep = 0;
|
||||
Active = true;
|
||||
Timer.Start ();
|
||||
}
|
||||
|
||||
public void Stop () {
|
||||
Active = false;
|
||||
Timer.Stop ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,145 +0,0 @@
|
|||
// SparkleShare, an instant update workflow to Git.
|
||||
// Copyright (C) 2010 Hylke Bons <hylkebons@gmail.com>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
using Gtk;
|
||||
using Mono.Unix;
|
||||
using SparkleShare;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace SparkleShare {
|
||||
|
||||
public class SparkleStatusIcon : StatusIcon {
|
||||
|
||||
// Short alias for the translations
|
||||
public static string _ (string s) {
|
||||
return Catalog.GetString (s);
|
||||
}
|
||||
|
||||
public SparkleStatusIcon () : base () {
|
||||
|
||||
Activate += delegate {
|
||||
|
||||
Menu Menu = new Menu();
|
||||
|
||||
MenuItem StatusItem = new MenuItem (_("Everything is up to date"));
|
||||
StatusItem.Sensitive = false;
|
||||
Menu.Add (StatusItem);
|
||||
Menu.Add (new SeparatorMenuItem ());
|
||||
|
||||
MenuItem [] FolderItems =
|
||||
new MenuItem [SparkleShare.Repositories.Length];
|
||||
|
||||
// TODO: For some strange reason both entries
|
||||
// open the same repo...
|
||||
int i = 0;
|
||||
foreach (SparkleRepo SparkleRepo in SparkleShare.Repositories) {
|
||||
FolderItems [i] = new MenuItem (SparkleRepo.Name);
|
||||
FolderItems [i].Activated += delegate {
|
||||
SparkleWindow SparkleWindow = new SparkleWindow (SparkleRepo);
|
||||
SparkleWindow.ShowAll ();
|
||||
};
|
||||
Menu.Add (FolderItems [i]);
|
||||
i++;
|
||||
}
|
||||
|
||||
MenuItem AddItem = new MenuItem (_("Add a Folder…"));
|
||||
AddItem.Activated += delegate {
|
||||
SparkleDialog SparkleDialog = new SparkleDialog ();
|
||||
SparkleDialog.ShowAll ();
|
||||
};
|
||||
Menu.Add (AddItem);
|
||||
Menu.Add (new SeparatorMenuItem ());
|
||||
|
||||
CheckMenuItem NotifyCheckMenuItem =
|
||||
new CheckMenuItem (_("Show notifications"));
|
||||
Menu.Add (NotifyCheckMenuItem);
|
||||
Menu.Add (new SeparatorMenuItem ());
|
||||
|
||||
|
||||
|
||||
string NotifyChangesFileName =
|
||||
SparkleHelpers.CombineMore (SparklePaths.SparkleConfigPath,
|
||||
"sparkleshare.notify");
|
||||
|
||||
if (System.IO.File.Exists (NotifyChangesFileName))
|
||||
NotifyCheckMenuItem.Active = true;
|
||||
|
||||
NotifyCheckMenuItem.Toggled += delegate {
|
||||
if (System.IO.File.Exists (NotifyChangesFileName)) {
|
||||
File.Delete (NotifyChangesFileName);
|
||||
} else {
|
||||
System.IO.File.Create (NotifyChangesFileName);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
MenuItem OpenFolderItem = new MenuItem (_("Open Sharing Folder"));
|
||||
OpenFolderItem.Activated += delegate {
|
||||
Process Process = new Process ();
|
||||
Process.StartInfo.FileName = "xdg-open";
|
||||
Process.StartInfo.Arguments = SparklePaths.SparklePath;
|
||||
Process.Start();
|
||||
};
|
||||
Menu.Add (OpenFolderItem);
|
||||
|
||||
MenuItem AboutItem = new MenuItem (_("Visit SparkleShare Website"));
|
||||
AboutItem.Activated += delegate {
|
||||
Process Process = new Process ();
|
||||
Process.StartInfo.FileName = "xdg-open";
|
||||
Process.StartInfo.Arguments = "http://www.sparkleshare.org/";
|
||||
Process.Start();
|
||||
};
|
||||
Menu.Add (AboutItem);
|
||||
|
||||
Menu.Add (new SeparatorMenuItem ());
|
||||
MenuItem QuitItem = new MenuItem ("Quit");
|
||||
QuitItem.Activated += delegate { Environment.Exit (0); };
|
||||
Menu.Add (QuitItem);
|
||||
|
||||
Menu.ShowAll ();
|
||||
Menu.Popup ();
|
||||
|
||||
};
|
||||
|
||||
SetIdleState ();
|
||||
|
||||
}
|
||||
|
||||
public void SetIdleState () {
|
||||
IconName = "folder-sparkleshare";
|
||||
}
|
||||
|
||||
public void SetSyncingState () {
|
||||
// IconName = "folder-syncing";
|
||||
}
|
||||
|
||||
public void SetErrorState () {
|
||||
// IconName = "folder-sync-error";
|
||||
}
|
||||
|
||||
// Quits the program
|
||||
public void Quit (object o, EventArgs args) {
|
||||
System.IO.File.Delete (SparkleHelpers.CombineMore (SparklePaths.SparkleTmpPath +
|
||||
"sparkleshare.pid"));
|
||||
Application.Quit ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,156 +0,0 @@
|
|||
// SparkleShare, an instant update workflow to Git.
|
||||
// Copyright (C) 2010 Hylke Bons <hylkebons@gmail.com>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
using Gtk;
|
||||
using SparkleShare;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
||||
namespace SparkleShare {
|
||||
|
||||
public class SparkleUI {
|
||||
|
||||
public static SparkleStatusIcon NotificationIcon;
|
||||
|
||||
public SparkleUI (bool HideUI) {
|
||||
|
||||
Process Process = new Process();
|
||||
Process.EnableRaisingEvents = false;
|
||||
Process.StartInfo.RedirectStandardOutput = true;
|
||||
Process.StartInfo.UseShellExecute = false;
|
||||
|
||||
string SparklePath = SparklePaths.SparklePath;
|
||||
|
||||
// Create 'SparkleShare' folder in the user's home folder
|
||||
// if it's not there already
|
||||
if (!Directory.Exists (SparklePath)) {
|
||||
Directory.CreateDirectory (SparklePath);
|
||||
Console.WriteLine ("[Config] Created '" + SparklePath + "'");
|
||||
|
||||
if (SparklePlatform.Name.Equals ("GNOME")) {
|
||||
|
||||
// Add a special icon to the SparkleShare folder
|
||||
Process.StartInfo.FileName = "gvfs-set-attribute";
|
||||
Process.StartInfo.Arguments = SparklePath +
|
||||
" metadata::custom-icon " +
|
||||
"file:///usr/share/icons/hicolor/" +
|
||||
"48x48/places/" +
|
||||
"folder-sparkleshare.png";
|
||||
Process.Start();
|
||||
|
||||
// Add the SparkleShare folder to the bookmarks
|
||||
string BookmarksFileName =
|
||||
Path.Combine (SparklePaths.HomePath, ".gtk-bookmarks");
|
||||
if (File.Exists (BookmarksFileName)) {
|
||||
TextWriter TextWriter = File.AppendText (BookmarksFileName);
|
||||
TextWriter.WriteLine ("file://" + SparklePath + " SparkleShare");
|
||||
TextWriter.Close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Get all the repos in ~/SparkleShare
|
||||
SparkleRepo [] TmpRepos =
|
||||
new SparkleRepo [Directory.GetDirectories (SparklePath).Length];
|
||||
|
||||
int i = 0;
|
||||
foreach (string Folder in Directory.GetDirectories (SparklePath)) {
|
||||
|
||||
// Check if the folder is a git repo
|
||||
if (Directory.Exists (SparkleHelpers.CombineMore (Folder,
|
||||
".git"))) {
|
||||
TmpRepos [i] = new SparkleRepo (Folder);
|
||||
i++;
|
||||
|
||||
// Attach emblems
|
||||
if (SparklePlatform.Name.Equals ("GNOME")) {
|
||||
Process.StartInfo.FileName = "gvfs-set-attribute";
|
||||
Process.StartInfo.Arguments = " file://" + Folder +
|
||||
" metadata::emblems " +
|
||||
"[synced]";
|
||||
Process.Start();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SparkleShare.Repositories = new SparkleRepo [i];
|
||||
Array.Copy (TmpRepos, SparkleShare.Repositories, i);
|
||||
|
||||
// Don't create the window and status
|
||||
// icon when --disable-gui was given
|
||||
if (!HideUI) {
|
||||
|
||||
// Create the status icon
|
||||
NotificationIcon = new SparkleStatusIcon ();
|
||||
|
||||
// Show a notification if there are no folders yet
|
||||
if (SparkleShare.Repositories.Length == 0) {
|
||||
|
||||
SparkleBubble NoFoldersBubble;
|
||||
NoFoldersBubble = new SparkleBubble ("Welcome to SparkleShare!",
|
||||
"You don't have any " +
|
||||
"folders set up yet.\n" +
|
||||
"Please create some in " +
|
||||
"the SparkleShare folder.");
|
||||
|
||||
NoFoldersBubble.IconName = "folder-sparkleshare";
|
||||
NoFoldersBubble.AddAction ("", "Open SparkleShare Folder", delegate {
|
||||
Process.StartInfo.FileName = "xdg-open";
|
||||
Process.StartInfo.Arguments = SparklePaths.SparklePath;
|
||||
Process.Start();
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Watch the SparkleShare folder and pop up the
|
||||
// Add dialog when a new folder is created
|
||||
FileSystemWatcher Watcher = new FileSystemWatcher (SparklePaths.SparklePath);
|
||||
Watcher.IncludeSubdirectories = false;
|
||||
Watcher.EnableRaisingEvents = true;
|
||||
Watcher.Created += delegate (object o, FileSystemEventArgs args) {
|
||||
WatcherChangeTypes wct = args.ChangeType;
|
||||
Console.WriteLine ("[Event][SparkleShare] " + wct.ToString() +
|
||||
" '" + args.Name + "'");
|
||||
SparkleDialog SparkleDialog = new SparkleDialog ();
|
||||
SparkleDialog.ShowAll ();
|
||||
};
|
||||
|
||||
// Create place to store configuration user's home folder
|
||||
string ConfigPath = SparklePaths.SparkleConfigPath;
|
||||
string AvatarPath = SparklePaths.SparkleAvatarPath;
|
||||
if (!Directory.Exists (ConfigPath)) {
|
||||
|
||||
Directory.CreateDirectory (ConfigPath);
|
||||
Console.WriteLine ("[Config] Created '" + ConfigPath + "'");
|
||||
|
||||
// Create a place to store the avatars
|
||||
Directory.CreateDirectory (AvatarPath);
|
||||
Console.WriteLine ("[Config] Created '" + AvatarPath + "avatars'");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,300 +0,0 @@
|
|||
// SparkleShare, an instant update workflow to Git.
|
||||
// Copyright (C) 2010 Hylke Bons <hylkebons@gmail.com>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
using Gtk;
|
||||
using Mono.Unix;
|
||||
using SparkleShare;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Timers;
|
||||
|
||||
namespace SparkleShare {
|
||||
|
||||
public class SparkleWindow : Window {
|
||||
|
||||
// Short alias for the translations
|
||||
public static string _ (string s) {
|
||||
return Catalog.GetString (s);
|
||||
}
|
||||
|
||||
private SparkleRepo SparkleRepo;
|
||||
private VBox LayoutHorizontal;
|
||||
private ScrolledWindow LogScrolledWindow;
|
||||
private ScrolledWindow PeopleScrolledWindow;
|
||||
private string SelectedEmail;
|
||||
|
||||
public SparkleWindow (SparkleRepo Repo) : base ("") {
|
||||
|
||||
SparkleRepo = Repo;
|
||||
SelectedEmail = "";
|
||||
|
||||
SetSizeRequest (720, 540);
|
||||
SetPosition (WindowPosition.Center);
|
||||
BorderWidth = 6;
|
||||
Title = _("‘" + SparkleRepo.Name + "’ on " +
|
||||
SparkleRepo.RemoteOriginUrl
|
||||
.TrimEnd (("/" + SparkleRepo.Name).ToCharArray ()));
|
||||
IconName = "folder-sparkleshare";
|
||||
|
||||
VBox LayoutVertical = new VBox (false, 0);
|
||||
|
||||
LayoutHorizontal = new VBox (false, 6);
|
||||
LayoutHorizontal.BorderWidth = 6;
|
||||
LayoutHorizontal.PackStart (CreatePeopleList (), false, false, 0);
|
||||
LayoutHorizontal.PackStart (CreateEventLog (), true, true, 0);
|
||||
|
||||
LayoutVertical.PackStart (LayoutHorizontal, true, true, 0);
|
||||
|
||||
HButtonBox DialogButtons = new HButtonBox ();
|
||||
DialogButtons.Layout = ButtonBoxStyle.End;
|
||||
DialogButtons.BorderWidth = 6;
|
||||
|
||||
Button CloseButton = new Button (Stock.Close);
|
||||
CloseButton.Clicked += delegate (object o, EventArgs args) {
|
||||
Destroy ();
|
||||
};
|
||||
|
||||
DialogButtons.Add (CloseButton);
|
||||
|
||||
LayoutVertical.PackStart (DialogButtons, false, false, 0);
|
||||
|
||||
/* Timer RedrawTimer = new Timer ();
|
||||
RedrawTimer.Interval = 5000;
|
||||
RedrawTimer.Elapsed += delegate {
|
||||
UpdatePeopleList ();
|
||||
UpdateEventLog ();
|
||||
};
|
||||
RedrawTimer.Start();
|
||||
*/
|
||||
Add (LayoutVertical);
|
||||
|
||||
}
|
||||
|
||||
public void UpdateEventLog () {
|
||||
LayoutHorizontal.Remove (LogScrolledWindow);
|
||||
LogScrolledWindow = CreateEventLog ();
|
||||
LayoutHorizontal.PackStart (LogScrolledWindow, true, true, 0);
|
||||
ShowAll ();
|
||||
}
|
||||
|
||||
public void UpdatePeopleList () {
|
||||
LayoutHorizontal.Remove (PeopleScrolledWindow);
|
||||
PeopleScrolledWindow = CreatePeopleList ();
|
||||
LayoutHorizontal.PackStart (PeopleScrolledWindow, false, false, 0);
|
||||
LayoutHorizontal.ReorderChild (PeopleScrolledWindow, 0);
|
||||
ShowAll ();
|
||||
}
|
||||
|
||||
public ScrolledWindow CreateEventLog () {
|
||||
|
||||
ListStore LogStore = new ListStore (typeof (Gdk.Pixbuf),
|
||||
typeof (string),
|
||||
typeof (string),
|
||||
typeof (string));
|
||||
|
||||
Process Process = new Process();
|
||||
Process.EnableRaisingEvents = false;
|
||||
Process.StartInfo.RedirectStandardOutput = true;
|
||||
Process.StartInfo.UseShellExecute = false;
|
||||
Process.StartInfo.FileName = "git";
|
||||
|
||||
string Output = "";
|
||||
|
||||
Process.StartInfo.WorkingDirectory = SparkleRepo.LocalPath;
|
||||
// We're using the snowman here to separate messages :)
|
||||
Process.StartInfo.Arguments =
|
||||
"log --format=\"%at☃%an %s☃%cr☃%ae\" -25";
|
||||
Process.Start();
|
||||
|
||||
Output += "\n" + Process.StandardOutput.ReadToEnd().Trim ();
|
||||
|
||||
Output = Output.TrimStart ("\n".ToCharArray ());
|
||||
string [] Lines = Regex.Split (Output, "\n");
|
||||
|
||||
// Sort by time and get the last 25
|
||||
Array.Sort (Lines);
|
||||
Array.Reverse (Lines);
|
||||
|
||||
TreeIter Iter;
|
||||
for (int i = 0; i < 25 && i < Lines.Length; i++) {
|
||||
|
||||
string Line = Lines [i];
|
||||
if (Line.Contains (SelectedEmail)) {
|
||||
|
||||
// Look for the snowman!
|
||||
string [] Parts = Regex.Split (Line, "☃");
|
||||
string Message = Parts [1];
|
||||
string TimeAgo = Parts [2];
|
||||
string UserEmail = Parts [3];
|
||||
|
||||
string IconFile = "document-edited";
|
||||
|
||||
if (Message.IndexOf (" added ‘") > -1)
|
||||
IconFile = "document-added";
|
||||
|
||||
if (Message.IndexOf (" deleted ‘") > -1)
|
||||
IconFile = "document-removed";
|
||||
|
||||
if (Message.IndexOf (" moved ‘") > -1 ||
|
||||
Message.IndexOf (" renamed ‘") > -1)
|
||||
IconFile = "document-moved";
|
||||
|
||||
Gdk.Pixbuf ChangeIcon = SparkleHelpers.GetIcon (IconFile, 16);
|
||||
Iter = LogStore.Append ();
|
||||
LogStore.SetValue (Iter, 0, ChangeIcon);
|
||||
LogStore.SetValue (Iter, 1, Message);
|
||||
LogStore.SetValue (Iter, 2, " " + TimeAgo);
|
||||
|
||||
// We're not showing e-mail, it's only
|
||||
// there for lookup purposes
|
||||
LogStore.SetValue (Iter, 3, UserEmail);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TreeView LogView = new TreeView (LogStore);
|
||||
LogView.HeadersVisible = false;
|
||||
|
||||
CellRendererText TextCellRight = new Gtk.CellRendererText ();
|
||||
TextCellRight.Alignment = Pango.Alignment.Right;
|
||||
|
||||
CellRendererText TextCellMiddle = new Gtk.CellRendererText ();
|
||||
TextCellMiddle.Ellipsize = Pango.EllipsizeMode.End;
|
||||
|
||||
LogView.AppendColumn ("", new Gtk.CellRendererPixbuf (), "pixbuf", 0);
|
||||
LogView.AppendColumn ("", TextCellMiddle, "text", 1);
|
||||
LogView.AppendColumn ("", TextCellRight, "text", 2);
|
||||
|
||||
TreeViewColumn [] Columns = LogView.Columns;
|
||||
Columns [0].MinWidth = 32;
|
||||
Columns [1].Expand = true;
|
||||
Columns [1].MaxWidth = 150;
|
||||
|
||||
LogView.CursorChanged += delegate(object o, EventArgs args) {
|
||||
TreeModel model;
|
||||
if (LogView.Selection.GetSelected (out model, out Iter)) {
|
||||
SelectedEmail = (string) LogStore.GetValue (Iter, 3);
|
||||
UpdatePeopleList ();
|
||||
}
|
||||
};
|
||||
|
||||
LogScrolledWindow = new ScrolledWindow ();
|
||||
LogScrolledWindow.AddWithViewport (LogView);
|
||||
|
||||
return LogScrolledWindow;
|
||||
|
||||
}
|
||||
|
||||
// Creates a visual list of people working in the repo
|
||||
public ScrolledWindow CreatePeopleList () {
|
||||
|
||||
Process Process = new Process ();
|
||||
Process.EnableRaisingEvents = false;
|
||||
Process.StartInfo.RedirectStandardOutput = true;
|
||||
Process.StartInfo.UseShellExecute = false;
|
||||
|
||||
// Get a log of commits, example: "Hylke Bons☃added 'file'."
|
||||
Process.StartInfo.FileName = "git";
|
||||
Process.StartInfo.Arguments = "log --format=\"%an☃%ae\" -50";
|
||||
Process.StartInfo.WorkingDirectory = SparkleRepo.LocalPath;
|
||||
Process.Start();
|
||||
|
||||
string Output = Process.StandardOutput.ReadToEnd().Trim ();
|
||||
string [] People = new string [50];
|
||||
string [] Lines = Regex.Split (Output, "\n");
|
||||
|
||||
ListStore PeopleStore = new ListStore (typeof (Gdk.Pixbuf),
|
||||
typeof (string),
|
||||
typeof (string));
|
||||
|
||||
int i = 0;
|
||||
TreeIter Iter;
|
||||
TreePath TreePath = new TreePath ();
|
||||
foreach (string Line in Lines) {
|
||||
|
||||
// Only add name if it isn't there already
|
||||
if (Array.IndexOf (People, Line) == -1) {
|
||||
|
||||
People [i] = Line;
|
||||
string [] Parts = Regex.Split (Line, "☃");
|
||||
|
||||
string UserName = Parts [0];
|
||||
string UserEmail = Parts [1];
|
||||
|
||||
// Do something special if the person is you
|
||||
if (UserEmail.Equals (SparkleRepo.UserEmail))
|
||||
UserName += _(" (that’s you!)");
|
||||
|
||||
// Actually add to the list
|
||||
Iter = PeopleStore.Prepend ();
|
||||
PeopleStore.SetValue (Iter, 0,
|
||||
SparkleHelpers.GetAvatar (UserEmail , 32));
|
||||
PeopleStore.SetValue (Iter, 1,
|
||||
"<b>" + UserName + "</b>\n" +
|
||||
"<span font_size=\"smaller\">" +
|
||||
UserEmail + "</span>");
|
||||
PeopleStore.SetValue (Iter, 2, UserEmail);
|
||||
|
||||
if (UserEmail.Equals (SelectedEmail)) {
|
||||
TreePath = PeopleStore.GetPath (Iter);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
i++;
|
||||
|
||||
}
|
||||
|
||||
IconView PeopleView = new IconView (PeopleStore);
|
||||
PeopleView.PixbufColumn = 0;
|
||||
PeopleView.MarkupColumn = 1;
|
||||
PeopleView.Columns = 3;
|
||||
PeopleView.Spacing = 6;
|
||||
PeopleView.ItemWidth = 200;
|
||||
PeopleView.Orientation = Orientation.Horizontal;
|
||||
PeopleView.SelectionMode = SelectionMode.Single;
|
||||
|
||||
// TODO: doesn't work. Always seems to select the
|
||||
// first row :(
|
||||
PeopleView.SelectPath (TreePath);
|
||||
|
||||
PeopleView.SelectionChanged += delegate (object o, EventArgs args) {
|
||||
if (PeopleView.SelectedItems.Length > 0) {
|
||||
PeopleStore.GetIter (out Iter, PeopleView.SelectedItems [0]);
|
||||
string NewSelectedEmail = (string) PeopleStore.GetValue (Iter, 2);
|
||||
if (NewSelectedEmail.Equals (SelectedEmail)) {
|
||||
SelectedEmail = "";
|
||||
PeopleView.UnselectAll ();
|
||||
} else
|
||||
SelectedEmail = NewSelectedEmail;
|
||||
} else SelectedEmail = "";
|
||||
UpdateEventLog ();
|
||||
};
|
||||
|
||||
PeopleScrolledWindow = new ScrolledWindow ();
|
||||
PeopleScrolledWindow.AddWithViewport (PeopleView);
|
||||
PeopleScrolledWindow.HeightRequest = 200;
|
||||
|
||||
return PeopleScrolledWindow;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue