rename stuff and add separate bubble class
This commit is contained in:
parent
699f791faf
commit
c626cdfcce
100
SparkleShare/Main.cs
Normal file
100
SparkleShare/Main.cs
Normal file
|
@ -0,0 +1,100 @@
|
|||
// 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.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Timers;
|
||||
|
||||
namespace SparkleShare {
|
||||
|
||||
// This is SparkleShare!
|
||||
public class SparkleShare {
|
||||
|
||||
public static SparkleUI SparkleUI;
|
||||
|
||||
public static void Main (string [] args) {
|
||||
|
||||
// Check if git is installed
|
||||
Process Process = new Process();
|
||||
Process.StartInfo.RedirectStandardOutput = true;
|
||||
Process.StartInfo.UseShellExecute = false;
|
||||
Process.StartInfo.FileName = "git";
|
||||
Process.Start();
|
||||
if (Process.StandardOutput.ReadToEnd().IndexOf ("version") == -1) {
|
||||
Console.WriteLine ("Git wasn't found.");
|
||||
Console.WriteLine ("You can get it 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 as root.");
|
||||
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);
|
||||
SparkleUI.StartMonitoring ();
|
||||
|
||||
Gtk.Application.Run ();
|
||||
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
460
SparkleShare/Repository.cs
Normal file
460
SparkleShare/Repository.cs
Normal file
|
@ -0,0 +1,460 @@
|
|||
// 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.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Timers;
|
||||
|
||||
namespace SparkleShare {
|
||||
|
||||
// Repository class holds repository information and timers
|
||||
public class Repository {
|
||||
|
||||
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 bool MonitorOnly;
|
||||
|
||||
public Repository (string Path) {
|
||||
|
||||
MonitorOnly = false;
|
||||
|
||||
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 = Path;
|
||||
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"
|
||||
|
||||
string s = LocalPath.TrimEnd ( "/".ToCharArray ());
|
||||
Name = LocalPath.Substring (s.LastIndexOf ("/") + 1);
|
||||
|
||||
// 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 = 20000;
|
||||
FetchTimer.Elapsed += delegate {
|
||||
Fetch ();
|
||||
|
||||
};
|
||||
|
||||
FetchTimer.Start();
|
||||
BufferTimer = new Timer ();
|
||||
|
||||
// Add everything that changed
|
||||
// since SparkleShare was stopped
|
||||
Add ();
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Starts a time buffer when something changes
|
||||
public void OnFileActivity (object o, FileSystemEventArgs args) {
|
||||
WatcherChangeTypes wct = args.ChangeType;
|
||||
if (!ShouldIgnore (args.Name) && !MonitorOnly) {
|
||||
Console.WriteLine("[Event][" + Name + "] " + wct.ToString() +
|
||||
" '" + args.Name + "'");
|
||||
StartBufferTimer ();
|
||||
}
|
||||
}
|
||||
|
||||
// A buffer that will fetch changes after
|
||||
// file activity has settles down
|
||||
public void StartBufferTimer () {
|
||||
|
||||
int Interval = 2000;
|
||||
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 ();
|
||||
};
|
||||
|
||||
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();
|
||||
|
||||
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();
|
||||
ShowEventBubble (UserName + " " + Message,
|
||||
GetAvatarFileName (UserEmail, 48), true);
|
||||
}
|
||||
|
||||
// Fetches changes from the remote repo
|
||||
public void Fetch () {
|
||||
// TODO: change status icon to sync
|
||||
FetchTimer.Stop ();
|
||||
Console.WriteLine ("[Git][" + Name + "] Fetching changes...");
|
||||
Process.StartInfo.Arguments = "fetch";
|
||||
Process.Start();
|
||||
Process.WaitForExit ();
|
||||
Merge ();
|
||||
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 ();
|
||||
string Output = Process.StandardOutput.ReadToEnd().Trim ();
|
||||
|
||||
// Show notification if there are updates
|
||||
if (!Output.Equals ("Already up-to-date.")) {
|
||||
|
||||
// Get the last commit message
|
||||
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 ();
|
||||
|
||||
ShowEventBubble (LastCommitUserName + " " + LastCommitMessage,
|
||||
GetAvatarFileName (LastCommitEmail, 48), true);
|
||||
|
||||
}
|
||||
|
||||
Watcher.EnableRaisingEvents = true;
|
||||
// TODO: change status icon to normal
|
||||
}
|
||||
|
||||
// Pushes the changes to the remote repo
|
||||
public void Push () {
|
||||
// TODO: What happens when network disconnects during a push
|
||||
Console.WriteLine ("[Git][" + Name + "] Pushing changes...");
|
||||
Process.StartInfo.Arguments = "push";
|
||||
Process.Start();
|
||||
Process.WaitForExit ();
|
||||
}
|
||||
|
||||
// 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,
|
||||
string IconFileName,
|
||||
bool ShowButtons) {
|
||||
|
||||
SparkleBubble StuffChangedBubble = new SparkleBubble (Title, "");
|
||||
StuffChangedBubble.Icon = new Gdk.Pixbuf (IconFileName);
|
||||
|
||||
// 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";
|
||||
} );
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static string GetAvatarFileName (string Email, int Size) {
|
||||
|
||||
string AvatarPath = Environment.GetEnvironmentVariable("HOME") +
|
||||
"/.config/sparkleshare/avatars/" +
|
||||
Size + "x" + Size + "/";
|
||||
|
||||
if (!Directory.Exists (AvatarPath)) {
|
||||
Directory.CreateDirectory (AvatarPath);
|
||||
Console.WriteLine ("[Config] Created '" + AvatarPath + "'");
|
||||
|
||||
}
|
||||
string AvatarFile = AvatarPath + Email;
|
||||
|
||||
if (File.Exists (AvatarFile))
|
||||
return AvatarFile;
|
||||
|
||||
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 = "/tmp/" + 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);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
string FallbackFileName = "/usr/share/icons/hicolor/" +
|
||||
Size + "x" + Size +
|
||||
"/status/avatar-default.png";
|
||||
|
||||
if (File.Exists (FallbackFileName))
|
||||
return FallbackFileName;
|
||||
else
|
||||
return "/usr/share/icons/hicolor/16x16/status/avatar-default.png";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Helper that 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 ("-", "");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
31
SparkleShare/SparkleBubble.cs
Normal file
31
SparkleShare/SparkleBubble.cs
Normal file
|
@ -0,0 +1,31 @@
|
|||
// 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.Normal;
|
||||
Show ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
42
SparkleShare/SparkleShare.csproj
Normal file
42
SparkleShare/SparkleShare.csproj
Normal file
|
@ -0,0 +1,42 @@
|
|||
<?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>
|
||||
</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" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Main.cs" />
|
||||
<Compile Include="Repository.cs" />
|
||||
<Compile Include="SparkleUI.cs" />
|
||||
<Compile Include="SparkleStatusIcon.cs" />
|
||||
<Compile Include="SparkleWindow.cs" />
|
||||
<Compile Include="SparkleBubble.cs" />
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -28,9 +28,9 @@ using System.Timers;
|
|||
|
||||
namespace SparkleShare {
|
||||
|
||||
public class SparkleShareStatusIcon : StatusIcon {
|
||||
public class SparkleStatusIcon : StatusIcon {
|
||||
|
||||
public SparkleShareStatusIcon () : base () {
|
||||
public SparkleStatusIcon () : base () {
|
||||
|
||||
IconName = "folder-sparkleshare";
|
||||
|
116
SparkleShare/SparkleUI.cs
Normal file
116
SparkleShare/SparkleUI.cs
Normal file
|
@ -0,0 +1,116 @@
|
|||
// 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.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Timers;
|
||||
|
||||
namespace SparkleShare {
|
||||
|
||||
// Holds the status icon, window and repository list
|
||||
public class SparkleUI {
|
||||
|
||||
public SparkleWindow SparkleWindow;
|
||||
public SparkleStatusIcon SparkleStatusIcon;
|
||||
public Repository [] Repositories;
|
||||
|
||||
public SparkleUI (bool HideUI) {
|
||||
|
||||
Process Process = new Process();
|
||||
Process.EnableRaisingEvents = false;
|
||||
Process.StartInfo.RedirectStandardOutput = true;
|
||||
Process.StartInfo.UseShellExecute = false;
|
||||
|
||||
// Get home folder, example: "/home/user/"
|
||||
string UserHome = Environment.GetEnvironmentVariable("HOME") + "/";
|
||||
|
||||
// Create 'SparkleShare' folder in the user's home folder
|
||||
string ReposPath = UserHome + "SparkleShare";
|
||||
if (!Directory.Exists (ReposPath)) {
|
||||
Directory.CreateDirectory (ReposPath);
|
||||
Console.WriteLine ("[Config] Created '" + ReposPath + "'");
|
||||
|
||||
Process.StartInfo.FileName = "gvfs-set-attribute";
|
||||
Process.StartInfo.Arguments = ReposPath + " metadata::custom-icon " +
|
||||
"file://usr/share/icons/hicolor/48x48/places/folder-sparkleshare";
|
||||
Process.Start();
|
||||
|
||||
}
|
||||
|
||||
// Create place to store configuration user's home folder
|
||||
string ConfigPath = UserHome + ".config/sparkleshare/";
|
||||
if (!Directory.Exists (ConfigPath)) {
|
||||
|
||||
Directory.CreateDirectory (ConfigPath);
|
||||
Console.WriteLine ("[Config] Created '" + ConfigPath + "'");
|
||||
|
||||
// Create a first run file to show the intro message
|
||||
File.Create (ConfigPath + "firstrun");
|
||||
Console.WriteLine ("[Config] Created '" + ConfigPath + "firstrun'");
|
||||
|
||||
// Create a place to store the avatars
|
||||
Directory.CreateDirectory (ConfigPath + "avatars/");
|
||||
Console.WriteLine ("[Config] Created '" + ConfigPath + "avatars'");
|
||||
|
||||
}
|
||||
|
||||
// Get all the repos in ~/SparkleShare
|
||||
string [] Repos = Directory.GetDirectories (ReposPath);
|
||||
Repositories = new Repository [Repos.Length];
|
||||
|
||||
int i = 0;
|
||||
foreach (string Folder in Repos) {
|
||||
Repositories [i] = new Repository (Folder);
|
||||
i++;
|
||||
}
|
||||
|
||||
// Don't create the window and status
|
||||
// icon when --disable-gui was given
|
||||
if (!HideUI) {
|
||||
|
||||
// Create the window
|
||||
SparkleWindow = new SparkleWindow (Repositories);
|
||||
SparkleWindow.DeleteEvent += CloseSparkleWindow;
|
||||
|
||||
// Create the status icon
|
||||
SparkleStatusIcon = new SparkleStatusIcon ();
|
||||
SparkleStatusIcon.Activate += delegate {
|
||||
SparkleWindow.ToggleVisibility ();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Closes the window
|
||||
public void CloseSparkleWindow (object o, DeleteEventArgs args) {
|
||||
SparkleWindow = new SparkleWindow (Repositories);
|
||||
SparkleWindow.DeleteEvent += CloseSparkleWindow;
|
||||
}
|
||||
|
||||
public void StartMonitoring () { }
|
||||
public void StopMonitoring () { }
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -15,7 +15,6 @@
|
|||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
using Gtk;
|
||||
using Notifications;
|
||||
using SparkleShare;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
@ -29,7 +28,7 @@ using System.Timers;
|
|||
|
||||
namespace SparkleShare {
|
||||
|
||||
public class SparkleShareWindow : Window {
|
||||
public class SparkleWindow : Window {
|
||||
|
||||
private bool Visibility;
|
||||
private VBox LayoutVerticalLeft;
|
||||
|
@ -40,23 +39,21 @@ namespace SparkleShare {
|
|||
private ListStore ReposStore;
|
||||
private Repository [] Repositories;
|
||||
|
||||
public SparkleShareWindow (Repository [] R) : base ("SparkleShare") {
|
||||
public SparkleWindow (Repository [] R) : base ("SparkleShare") {
|
||||
|
||||
Repositories = R;
|
||||
|
||||
// Show a notification if there are no folders yet
|
||||
if (Repositories.Length == 0) {
|
||||
Notification Notification;
|
||||
Notification = new Notification ("Welcome to SparkleShare!",
|
||||
"You don't have any folders " +
|
||||
"configured yet.");
|
||||
|
||||
Notification.AddAction ("", "Add a Folder",
|
||||
delegate { CreateAddDialog (); } );
|
||||
SparkleBubble NoFoldersBubble;
|
||||
NoFoldersBubble = new SparkleBubble ("Welcome to SparkleShare!",
|
||||
"You don't have any folders " +
|
||||
"configured yet.");
|
||||
|
||||
NoFoldersBubble.AddAction ("", "Add a Folder",
|
||||
delegate { CreateAddDialog (); } );
|
||||
|
||||
Notification.Urgency = Urgency.Normal;
|
||||
Notification.Timeout = 7500;
|
||||
Notification.Show ();
|
||||
|
||||
} else {
|
||||
|
||||
|
@ -440,11 +437,11 @@ namespace SparkleShare {
|
|||
|
||||
public void CreateAddDialog () {
|
||||
|
||||
Window AddDialog = new Window ("Add Folder");
|
||||
Window AddDialog = new Window ("");
|
||||
AddDialog.SetPosition (WindowPosition.Center);
|
||||
// AddDialog.SetSizeRequest (320, 200);
|
||||
AddDialog.BorderWidth = 6;
|
||||
|
||||
AddDialog.IconName = "folder-sparkleshare";
|
||||
|
||||
Label NameLabel = new Label ("Folder Name: ");
|
||||
Entry NameEntry = new Entry ();
|
Loading…
Reference in a new issue