rename stuff and add separate bubble class

This commit is contained in:
Hylke Bons 2010-05-05 01:17:08 +01:00
parent 699f791faf
commit c626cdfcce
7 changed files with 762 additions and 16 deletions

100
SparkleShare/Main.cs Normal file
View 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
View 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 ("-", "");
}
}
}

View 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 ();
}
}
}

View 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>

View file

@ -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
View 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 () { }
}
}

View file

@ -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 ();