PageRenderTime 81ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 1ms

/GitUI/Dashboard.cs

https://github.com/eisnerd/gitextensions
C# | 404 lines | 340 code | 53 blank | 11 comment | 45 complexity | 20b16f81ea47db7ade667c6b690cfd00 MD5 | raw file
Possible License(s): GPL-3.0, GPL-2.0
  1. using System;
  2. using System.IO;
  3. using System.Diagnostics;
  4. using System.Drawing;
  5. using System.Linq;
  6. using System.Text.RegularExpressions;
  7. using System.Windows.Forms;
  8. using GitCommands.Repository;
  9. using GitUI.Properties;
  10. using GitUI.RepoHosting;
  11. using GitUIPluginInterfaces.RepositoryHosts;
  12. using ResourceManager.Translation;
  13. using Settings = GitCommands.Settings;
  14. using System.Configuration;
  15. namespace GitUI
  16. {
  17. public partial class Dashboard : GitExtensionsControl
  18. {
  19. private readonly TranslationString cloneFork = new TranslationString("Clone {0} repository");
  20. private readonly TranslationString cloneRepository = new TranslationString("Clone repository");
  21. private readonly TranslationString cloneSvnRepository = new TranslationString("Clone SVN repository");
  22. private readonly TranslationString createRepository = new TranslationString("Create new repository");
  23. private readonly TranslationString develop = new TranslationString("Develop");
  24. private readonly TranslationString donate = new TranslationString("Donate");
  25. private readonly TranslationString issues = new TranslationString("Issues");
  26. private readonly TranslationString openRepository = new TranslationString("Open repository");
  27. private readonly TranslationString translate = new TranslationString("Translate");
  28. private readonly TranslationString directoryIsNotAValidRepositoryCaption = new TranslationString("Open");
  29. private readonly TranslationString directoryIsNotAValidRepository = new TranslationString("The selected item is not a valid git repository.\n\nDo you want to abort and remove it from the recent repositories list?");
  30. private bool initialized;
  31. public Dashboard()
  32. {
  33. InitializeComponent();
  34. Translate();
  35. RecentRepositories.DashboardItemClick += dashboardItem_Click;
  36. RecentRepositories.RepositoryRemoved += RecentRepositories_RepositoryRemoved;
  37. RecentRepositories.DisableContextMenu();
  38. RecentRepositories.DashboardCategoryChanged += dashboardCategory_DashboardCategoryChanged;
  39. //Repositories.RepositoryCategories.ListChanged += new ListChangedEventHandler(RepositoryCategories_ListChanged);
  40. Bitmap image = Lemmings.GetPictureBoxImage(DateTime.Now);
  41. if (image != null)
  42. {
  43. pictureBox1.Image = image;
  44. }
  45. // Do this at runtime, because it is difficult to keep consistent at design time.
  46. pictureBox1.BringToFront();
  47. pictureBox1.Location = new Point(this.Width - pictureBox1.Image.Width - 10, this.Height - pictureBox1.Image.Height - 10);
  48. Load += Dashboard_Load;
  49. }
  50. void RecentRepositories_RepositoryRemoved(Repository repository)
  51. {
  52. if (repository != null)
  53. Repositories.RepositoryHistory.RemoveRepository(repository);
  54. }
  55. private void Dashboard_Load(object sender, EventArgs e)
  56. {
  57. DonateCategory.Dock = DockStyle.Top;
  58. //Show buttons
  59. CommonActions.DisableContextMenu();
  60. var openItem = new DashboardItem(Resources.Folder, openRepository.Text);
  61. openItem.Click += openItem_Click;
  62. CommonActions.AddItem(openItem);
  63. var cloneItem = new DashboardItem(Resources.SaveAs, cloneRepository.Text);
  64. cloneItem.Click += cloneItem_Click;
  65. CommonActions.AddItem(cloneItem);
  66. var cloneSvnItem = new DashboardItem(Resources.SaveAs, cloneSvnRepository.Text);
  67. cloneSvnItem.Click += cloneSvnItem_Click;
  68. CommonActions.AddItem(cloneSvnItem);
  69. foreach (IRepositoryHostPlugin el in RepoHosts.GitHosters)
  70. {
  71. IRepositoryHostPlugin gitHoster = el;
  72. var di = new DashboardItem(Resources.SaveAs, string.Format(cloneFork.Text, el.Description));
  73. di.Click += (repoSender, eventArgs) => GitUICommands.Instance.StartCloneForkFromHoster(this, gitHoster);
  74. CommonActions.AddItem(di);
  75. }
  76. var createItem = new DashboardItem(Resources.Star, createRepository.Text);
  77. createItem.Click += createItem_Click;
  78. CommonActions.AddItem(createItem);
  79. DonateCategory.DisableContextMenu();
  80. var GitHubItem = new DashboardItem(Resources.develop.ToBitmap(), develop.Text);
  81. GitHubItem.Click += GitHubItem_Click;
  82. DonateCategory.AddItem(GitHubItem);
  83. var DonateItem = new DashboardItem(Resources.dollar.ToBitmap(), donate.Text);
  84. DonateItem.Click += DonateItem_Click;
  85. DonateCategory.AddItem(DonateItem);
  86. var TranslateItem = new DashboardItem(Resources.EditItem, translate.Text);
  87. TranslateItem.Click += TranslateItem_Click;
  88. DonateCategory.AddItem(TranslateItem);
  89. var IssuesItem = new DashboardItem(Resources.bug, issues.Text);
  90. IssuesItem.Click += IssuesItem_Click;
  91. DonateCategory.AddItem(IssuesItem);
  92. }
  93. public void SaveSplitterPositions()
  94. {
  95. try
  96. {
  97. Properties.Settings.Default.Dashboard_MainSplitContainer_SplitterDistance = splitContainer5.SplitterDistance;
  98. Properties.Settings.Default.Dashboard_CommonSplitContainer_SplitterDistance = splitContainer6.SplitterDistance;
  99. Properties.Settings.Default.Save();
  100. }
  101. catch (ConfigurationException)
  102. {
  103. //TODO: howto restore a corrupted config? Properties.Settings.Default.Reset() doesn't work.
  104. }
  105. }
  106. public event EventHandler WorkingDirChanged;
  107. public virtual void OnWorkingDirChanged()
  108. {
  109. if (WorkingDirChanged != null)
  110. WorkingDirChanged(this, null);
  111. }
  112. private void AddDashboardEntry(RepositoryCategory entry)
  113. {
  114. var dashboardCategory = new DashboardCategory(entry.Description, entry);
  115. this.groupLayoutPanel.Controls.Add(dashboardCategory);
  116. dashboardCategory.DashboardItemClick += dashboardItem_Click;
  117. dashboardCategory.DashboardCategoryChanged += dashboardCategory_DashboardCategoryChanged;
  118. }
  119. private void dashboardCategory_DashboardCategoryChanged(object sender, EventArgs e)
  120. {
  121. Refresh();
  122. }
  123. public override void Refresh()
  124. {
  125. initialized = false;
  126. ShowRecentRepositories();
  127. }
  128. public void ShowRecentRepositories()
  129. {
  130. if (!Visible)
  131. {
  132. return;
  133. }
  134. // Make sure the dashboard is only initialized once
  135. if (!initialized)
  136. {
  137. // Remove favorites
  138. var categories = (from DashboardCategory i in this.groupLayoutPanel.Controls
  139. select i).ToList();
  140. this.groupLayoutPanel.Controls.Clear();
  141. foreach (var category in categories)
  142. {
  143. category.DashboardCategoryChanged -= dashboardCategory_DashboardCategoryChanged;
  144. category.DashboardItemClick -= dashboardItem_Click;
  145. category.Clear();
  146. }
  147. // Show favorites
  148. foreach (var category in Repositories.RepositoryCategories)
  149. {
  150. AddDashboardEntry(category);
  151. }
  152. initialized = true;
  153. }
  154. splitContainer6.Panel1MinSize = 1;
  155. splitContainer6.Panel2MinSize = 1;
  156. splitContainer7.Panel1MinSize = 1;
  157. splitContainer7.Panel2MinSize = 1;
  158. RecentRepositories.Clear();
  159. RepositoryCategory filteredRecentRepositoryHistory = new RepositoryCategory();
  160. filteredRecentRepositoryHistory.Description = Repositories.RepositoryHistory.Description;
  161. filteredRecentRepositoryHistory.CategoryType = Repositories.RepositoryHistory.CategoryType;
  162. foreach (Repository repository in Repositories.RepositoryHistory.Repositories)
  163. {
  164. if (!Repositories.RepositoryCategories.Any(c => c.Repositories.Any(r => r.Path != null && r.Path.Equals(repository.Path, StringComparison.CurrentCultureIgnoreCase))))
  165. {
  166. repository.RepositoryType = RepositoryType.History;
  167. filteredRecentRepositoryHistory.Repositories.Add(repository);
  168. }
  169. }
  170. RecentRepositories.RepositoryCategory = filteredRecentRepositoryHistory;
  171. pictureBox1.BringToFront();
  172. SetSplitterPositions();
  173. }
  174. private void SetSplitterPositions()
  175. {
  176. try
  177. {
  178. SetSplitterDistance(
  179. splitContainer6,
  180. Properties.Settings.Default.Dashboard_CommonSplitContainer_SplitterDistance,
  181. (int)Math.Max(2, (CommonActions.Height * 1.2)));
  182. SetSplitterDistance(
  183. splitContainer7,
  184. 0, // No settings property for this splitter. Will use default always.
  185. Math.Max(2, splitContainer7.Height - (DonateCategory.Height + 25)));
  186. SetSplitterDistance(
  187. splitContainer5,
  188. Properties.Settings.Default.Dashboard_MainSplitContainer_SplitterDistance,
  189. 315);
  190. }
  191. catch (ConfigurationException)
  192. {
  193. //TODO: howto restore a corrupted config? Properties.Settings.Default.Reset() doesn't work.
  194. }
  195. }
  196. private void SetSplitterDistance(SplitContainer splitContainer, int value, int @default)
  197. {
  198. if (value != 0)
  199. {
  200. try
  201. {
  202. splitContainer.SplitterDistance = value;
  203. }
  204. catch
  205. {
  206. splitContainer.SplitterDistance = @default;
  207. }
  208. }
  209. else
  210. splitContainer.SplitterDistance = @default;
  211. }
  212. private void TranslateItem_Click(object sender, EventArgs e)
  213. {
  214. new FormTranslate().ShowDialog(this);
  215. }
  216. private static void GitHubItem_Click(object sender, EventArgs e)
  217. {
  218. Process.Start(@"http://github.com/spdr870/gitextensions");
  219. }
  220. private static void IssuesItem_Click(object sender, EventArgs e)
  221. {
  222. Process.Start(@"http://github.com/spdr870/gitextensions/issues");
  223. }
  224. private void dashboardItem_Click(object sender, EventArgs e)
  225. {
  226. var label = sender as DashboardItem;
  227. if (label == null || string.IsNullOrEmpty(label.Path))
  228. return;
  229. //Open urls in browser, but open directories in GitExtensions
  230. if (Regex.IsMatch(label.Path,
  231. @"^(?#Protocol)(?:(?:ht|f)tp(?:s?)\:\/\/|~\/|\/)?(?#Username:Password)(?:\w+:\w+@)?(?#Subdomains)(?:(?:[-\w]+\.)+(?#TopLevel Domains)(?:com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum|travel|[a-z]{2}))(?#Port)(?::[\d]{1,5})?(?#Directories)(?:(?:(?:\/(?:[-\w~!$+|.,=]|%[a-f\d]{2})+)+|\/)+|\?|#)?(?#Query)(?:(?:\?(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=?(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)(?:&(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=?(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)*)*(?#Anchor)(?:#(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)?$"))
  232. {
  233. Process.Start(label.Path);
  234. }
  235. else
  236. {
  237. OpenPath(label.Path);
  238. }
  239. }
  240. private void OpenPath(string path)
  241. {
  242. Settings.WorkingDir = path;
  243. if (!Settings.Module.ValidWorkingDir())
  244. {
  245. DialogResult dialogResult = MessageBox.Show(this, directoryIsNotAValidRepository.Text, directoryIsNotAValidRepositoryCaption.Text, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);
  246. if (dialogResult == DialogResult.Cancel)
  247. {
  248. Settings.WorkingDir = string.Empty;
  249. return;
  250. }
  251. if (dialogResult == DialogResult.Yes)
  252. {
  253. Settings.WorkingDir = string.Empty;
  254. Repositories.RepositoryHistory.RemoveRecentRepository(path);
  255. Refresh();
  256. return;
  257. }
  258. }
  259. Repositories.AddMostRecentRepository(Settings.WorkingDir);
  260. OnWorkingDirChanged();
  261. }
  262. private void openItem_Click(object sender, EventArgs e)
  263. {
  264. var open = new Open();
  265. open.ShowDialog(this);
  266. OnWorkingDirChanged();
  267. }
  268. private void cloneItem_Click(object sender, EventArgs e)
  269. {
  270. if (GitUICommands.Instance.StartCloneDialog(this))
  271. OnWorkingDirChanged();
  272. }
  273. private void cloneSvnItem_Click(object sender, EventArgs e)
  274. {
  275. if (GitUICommands.Instance.StartSvnCloneDialog(this))
  276. OnWorkingDirChanged();
  277. }
  278. private void createItem_Click(object sender, EventArgs e)
  279. {
  280. GitUICommands.Instance.StartInitializeDialog(this, Settings.WorkingDir);
  281. OnWorkingDirChanged();
  282. }
  283. private static void DonateItem_Click(object sender, EventArgs e)
  284. {
  285. Process.Start(
  286. @"https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=WAL2SSDV8ND54&lc=US&item_name=GitExtensions&no_note=1&no_shipping=1&currency_code=EUR&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted");
  287. }
  288. private void pictureBox1_Click(object sender, EventArgs e)
  289. {
  290. new FormDashboardEditor().ShowDialog(this);
  291. Refresh();
  292. }
  293. private void groupLayoutPanel_DragDrop(object sender, DragEventArgs e)
  294. {
  295. var fileNameArray = e.Data.GetData(DataFormats.FileDrop) as string[];
  296. if (fileNameArray != null)
  297. {
  298. if (fileNameArray.Length != 1)
  299. return;
  300. string dir = fileNameArray[0];
  301. if (!string.IsNullOrEmpty(dir) && Directory.Exists(dir))
  302. {
  303. OpenPath(dir);
  304. }
  305. return;
  306. }
  307. var text = e.Data.GetData(DataFormats.UnicodeText) as string;
  308. if (!string.IsNullOrEmpty(text))
  309. {
  310. var lines = text.Split('\n');
  311. if (lines.Length != 1)
  312. return;
  313. string url = lines[0];
  314. if (!string.IsNullOrEmpty(url))
  315. {
  316. if (GitUICommands.Instance.StartCloneDialog(this, url))
  317. OnWorkingDirChanged();
  318. }
  319. }
  320. }
  321. private void groupLayoutPanel_DragEnter(object sender, DragEventArgs e)
  322. {
  323. var fileNameArray = e.Data.GetData(DataFormats.FileDrop) as string[];
  324. if (fileNameArray != null)
  325. {
  326. if (fileNameArray.Length != 1)
  327. return;
  328. string dir = fileNameArray[0];
  329. if (!string.IsNullOrEmpty(dir) && Directory.Exists(dir))
  330. {
  331. //Allow drop (copy, not move) folders
  332. e.Effect = DragDropEffects.Copy;
  333. }
  334. return;
  335. }
  336. var text = e.Data.GetData(DataFormats.UnicodeText) as string;
  337. if (!string.IsNullOrEmpty(text))
  338. {
  339. var lines = text.Split('\n');
  340. if (lines.Length != 1)
  341. return;
  342. string url = lines[0];
  343. if (!string.IsNullOrEmpty(url))
  344. {
  345. //Allow drop (copy, not move) folders
  346. e.Effect = DragDropEffects.Copy;
  347. }
  348. }
  349. }
  350. }
  351. }