├── Screenshots
├── task.png
├── export.png
├── issue.png
├── sort1.gif
├── sort2.gif
├── export2.png
├── settings.gif
├── settings.png
├── main-window.png
├── new-project.png
└── visible-columns.gif
├── MiniBug
├── Resources
│ ├── MiniBug.png
│ ├── Minibug.ico
│ ├── Info_16x16.png
│ ├── Info_64x64.png
│ ├── About_32x32.png
│ ├── Delete_32x32.png
│ ├── EditBug_32x32.png
│ ├── NewBug_32x32.png
│ ├── NewTask_32x32.png
│ ├── Priority_High.png
│ ├── CloneBug_32x32.png
│ ├── CloneTask_32x32.png
│ ├── DeleteBug_32x32.png
│ ├── EditTask_32x32.png
│ ├── FileError_64x64.png
│ ├── Priority_Urgent.png
│ ├── Settings_32x32.png
│ ├── StatusOK_16x16.png
│ ├── DeleteTask_32x32.png
│ ├── FolderError_64x64.png
│ ├── NewProject_32x32.png
│ ├── OpenProject_32x32.png
│ ├── Priority_Immediate.png
│ ├── ConfigureView_32x32.png
│ ├── CriticalError_64x64.png
│ ├── MiniBug- about-image.png
│ ├── StatusWarning_16x16.png
│ └── StatusCriticalError_16x16.png
├── Classes
│ ├── ComboBoxItem.cs
│ ├── GridColumn.cs
│ ├── Extensions.cs
│ ├── GridTasksSortSettings.cs
│ ├── GridIssuesSortSettings.cs
│ ├── ImportExportResult.cs
│ ├── Task.cs
│ ├── Issue.cs
│ ├── TasksDataGridViewRowComparer.cs
│ ├── ApplicationData.cs
│ ├── IssuesDataGridViewRowComparer.cs
│ └── Project.cs
├── packages.config
├── Program.cs
├── AboutForm.cs
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Settings.settings
│ └── Settings.Designer.cs
├── App.config
├── FeedbackForm.Designer.cs
├── ProjectForm.cs
├── IssueForm.resx
├── TaskForm.resx
├── FeedbackForm.resx
├── ConfigureViewForm.resx
├── ImportExportFeedbackForm.resx
├── SettingsForm.resx
├── ExportForm.resx
├── ProjectForm.resx
├── AboutForm.Designer.cs
├── MainForm.resx
├── ImportExportFeedbackForm.Designer.cs
├── AboutForm.resx
├── FeedbackForm.cs
├── TaskForm.cs
├── ExportForm.cs
├── IssueForm.cs
└── ConfigureViewForm.Designer.cs
├── LICENSE
├── MiniBug.sln
├── .gitattributes
├── README.md
└── .gitignore
/Screenshots/task.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaomartiniano/MiniBug/HEAD/Screenshots/task.png
--------------------------------------------------------------------------------
/Screenshots/export.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaomartiniano/MiniBug/HEAD/Screenshots/export.png
--------------------------------------------------------------------------------
/Screenshots/issue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaomartiniano/MiniBug/HEAD/Screenshots/issue.png
--------------------------------------------------------------------------------
/Screenshots/sort1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaomartiniano/MiniBug/HEAD/Screenshots/sort1.gif
--------------------------------------------------------------------------------
/Screenshots/sort2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaomartiniano/MiniBug/HEAD/Screenshots/sort2.gif
--------------------------------------------------------------------------------
/Screenshots/export2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaomartiniano/MiniBug/HEAD/Screenshots/export2.png
--------------------------------------------------------------------------------
/Screenshots/settings.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaomartiniano/MiniBug/HEAD/Screenshots/settings.gif
--------------------------------------------------------------------------------
/Screenshots/settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaomartiniano/MiniBug/HEAD/Screenshots/settings.png
--------------------------------------------------------------------------------
/Screenshots/main-window.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaomartiniano/MiniBug/HEAD/Screenshots/main-window.png
--------------------------------------------------------------------------------
/Screenshots/new-project.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaomartiniano/MiniBug/HEAD/Screenshots/new-project.png
--------------------------------------------------------------------------------
/MiniBug/Resources/MiniBug.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaomartiniano/MiniBug/HEAD/MiniBug/Resources/MiniBug.png
--------------------------------------------------------------------------------
/MiniBug/Resources/Minibug.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaomartiniano/MiniBug/HEAD/MiniBug/Resources/Minibug.ico
--------------------------------------------------------------------------------
/MiniBug/Resources/Info_16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaomartiniano/MiniBug/HEAD/MiniBug/Resources/Info_16x16.png
--------------------------------------------------------------------------------
/MiniBug/Resources/Info_64x64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaomartiniano/MiniBug/HEAD/MiniBug/Resources/Info_64x64.png
--------------------------------------------------------------------------------
/Screenshots/visible-columns.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaomartiniano/MiniBug/HEAD/Screenshots/visible-columns.gif
--------------------------------------------------------------------------------
/MiniBug/Resources/About_32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaomartiniano/MiniBug/HEAD/MiniBug/Resources/About_32x32.png
--------------------------------------------------------------------------------
/MiniBug/Resources/Delete_32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaomartiniano/MiniBug/HEAD/MiniBug/Resources/Delete_32x32.png
--------------------------------------------------------------------------------
/MiniBug/Resources/EditBug_32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaomartiniano/MiniBug/HEAD/MiniBug/Resources/EditBug_32x32.png
--------------------------------------------------------------------------------
/MiniBug/Resources/NewBug_32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaomartiniano/MiniBug/HEAD/MiniBug/Resources/NewBug_32x32.png
--------------------------------------------------------------------------------
/MiniBug/Resources/NewTask_32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaomartiniano/MiniBug/HEAD/MiniBug/Resources/NewTask_32x32.png
--------------------------------------------------------------------------------
/MiniBug/Resources/Priority_High.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaomartiniano/MiniBug/HEAD/MiniBug/Resources/Priority_High.png
--------------------------------------------------------------------------------
/MiniBug/Resources/CloneBug_32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaomartiniano/MiniBug/HEAD/MiniBug/Resources/CloneBug_32x32.png
--------------------------------------------------------------------------------
/MiniBug/Resources/CloneTask_32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaomartiniano/MiniBug/HEAD/MiniBug/Resources/CloneTask_32x32.png
--------------------------------------------------------------------------------
/MiniBug/Resources/DeleteBug_32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaomartiniano/MiniBug/HEAD/MiniBug/Resources/DeleteBug_32x32.png
--------------------------------------------------------------------------------
/MiniBug/Resources/EditTask_32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaomartiniano/MiniBug/HEAD/MiniBug/Resources/EditTask_32x32.png
--------------------------------------------------------------------------------
/MiniBug/Resources/FileError_64x64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaomartiniano/MiniBug/HEAD/MiniBug/Resources/FileError_64x64.png
--------------------------------------------------------------------------------
/MiniBug/Resources/Priority_Urgent.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaomartiniano/MiniBug/HEAD/MiniBug/Resources/Priority_Urgent.png
--------------------------------------------------------------------------------
/MiniBug/Resources/Settings_32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaomartiniano/MiniBug/HEAD/MiniBug/Resources/Settings_32x32.png
--------------------------------------------------------------------------------
/MiniBug/Resources/StatusOK_16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaomartiniano/MiniBug/HEAD/MiniBug/Resources/StatusOK_16x16.png
--------------------------------------------------------------------------------
/MiniBug/Resources/DeleteTask_32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaomartiniano/MiniBug/HEAD/MiniBug/Resources/DeleteTask_32x32.png
--------------------------------------------------------------------------------
/MiniBug/Resources/FolderError_64x64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaomartiniano/MiniBug/HEAD/MiniBug/Resources/FolderError_64x64.png
--------------------------------------------------------------------------------
/MiniBug/Resources/NewProject_32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaomartiniano/MiniBug/HEAD/MiniBug/Resources/NewProject_32x32.png
--------------------------------------------------------------------------------
/MiniBug/Resources/OpenProject_32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaomartiniano/MiniBug/HEAD/MiniBug/Resources/OpenProject_32x32.png
--------------------------------------------------------------------------------
/MiniBug/Resources/Priority_Immediate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaomartiniano/MiniBug/HEAD/MiniBug/Resources/Priority_Immediate.png
--------------------------------------------------------------------------------
/MiniBug/Resources/ConfigureView_32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaomartiniano/MiniBug/HEAD/MiniBug/Resources/ConfigureView_32x32.png
--------------------------------------------------------------------------------
/MiniBug/Resources/CriticalError_64x64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaomartiniano/MiniBug/HEAD/MiniBug/Resources/CriticalError_64x64.png
--------------------------------------------------------------------------------
/MiniBug/Resources/MiniBug- about-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaomartiniano/MiniBug/HEAD/MiniBug/Resources/MiniBug- about-image.png
--------------------------------------------------------------------------------
/MiniBug/Resources/StatusWarning_16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaomartiniano/MiniBug/HEAD/MiniBug/Resources/StatusWarning_16x16.png
--------------------------------------------------------------------------------
/MiniBug/Resources/StatusCriticalError_16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaomartiniano/MiniBug/HEAD/MiniBug/Resources/StatusCriticalError_16x16.png
--------------------------------------------------------------------------------
/MiniBug/Classes/ComboBoxItem.cs:
--------------------------------------------------------------------------------
1 | // Copyright(c) João Martiniano. All rights reserved.
2 | // Licensed under the MIT license.
3 |
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 |
10 | namespace MiniBug
11 | {
12 | public class ComboBoxItem
13 | {
14 | public int Value { get; set; }
15 | public string Text { get; set; }
16 |
17 | public ComboBoxItem(int value, string text)
18 | {
19 | Value = value;
20 | Text = text;
21 | }
22 |
23 | public override string ToString()
24 | {
25 | return Text;
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/MiniBug/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/MiniBug/Program.cs:
--------------------------------------------------------------------------------
1 | // Copyright(c) João Martiniano. All rights reserved.
2 | // Licensed under the MIT license.
3 |
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using System.Threading.Tasks;
8 | using System.Windows.Forms;
9 |
10 | namespace MiniBug
11 | {
12 | static class Program
13 | {
14 | ///
15 | /// A software project that this application will work with. Contains issues and tasks.
16 | ///
17 | public static Project SoftwareProject = null;
18 |
19 | ///
20 | /// The main entry point for the application.
21 | ///
22 | [STAThread]
23 | static void Main()
24 | {
25 | Application.EnableVisualStyles();
26 | Application.SetCompatibleTextRenderingDefault(false);
27 | Application.Run(new MainForm());
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 João Martiniano
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/MiniBug.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28307.168
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MiniBug", "MiniBug\MiniBug.csproj", "{EF183892-A316-466B-B997-2BA7FAD4DB45}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {EF183892-A316-466B-B997-2BA7FAD4DB45}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {EF183892-A316-466B-B997-2BA7FAD4DB45}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {EF183892-A316-466B-B997-2BA7FAD4DB45}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {EF183892-A316-466B-B997-2BA7FAD4DB45}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {B34963BE-9B6F-47FF-B4C2-D61746118ABB}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/MiniBug/Classes/GridColumn.cs:
--------------------------------------------------------------------------------
1 | // Copyright(c) João Martiniano. All rights reserved.
2 | // Licensed under the MIT license.
3 |
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 |
10 | namespace MiniBug
11 | {
12 | ///
13 | /// A column in the issues or tasks DataGridView.
14 | ///
15 | public class GridColumn
16 | {
17 | /// Unique identification of this column in the issues DataGridView.
18 | public string Name { get; set; } = string.Empty;
19 |
20 | /// Header text of this column in the issues DataGridView.
21 | public string HeaderText { get; set; } = string.Empty;
22 |
23 | /// If true, this column is visible in the issues DataGridView.
24 | public bool Visible { get; set; } = false;
25 |
26 | /// The order of the column in the issues DataGridView. The first item has a value of 0.
27 | public int DisplayIndex { get; set; } = -1;
28 |
29 | /// A description of the column.
30 | public string Description { get; set; } = string.Empty;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/MiniBug/Classes/Extensions.cs:
--------------------------------------------------------------------------------
1 | // Copyright(c) João Martiniano. All rights reserved.
2 | // Licensed under the MIT license.
3 |
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.Reflection;
10 | using System.ComponentModel;
11 |
12 | namespace MiniBug
13 | {
14 | public static class ExtensionMethods
15 | {
16 | ///
17 | /// Returns a human-readable description of a member of a enum.
18 | ///
19 | /// The enum member.
20 | /// A string containing the description.
21 | public static string ToDescription(this Enum e)
22 | {
23 | // This code was adapted from: https://blogs.msdn.microsoft.com/abhinaba/2005/10/21/c-3-0-using-extension-methods-for-enum-tostring/
24 |
25 | Type type = e.GetType();
26 | MemberInfo[] memInfo = type.GetMember(e.ToString());
27 |
28 | if (memInfo != null && memInfo.Length > 0)
29 | {
30 | object[] attrs = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
31 |
32 | if (attrs != null && attrs.Length > 0)
33 | {
34 | return ((DescriptionAttribute)attrs[0]).Description;
35 | }
36 | }
37 |
38 | return e.ToString();
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/MiniBug/AboutForm.cs:
--------------------------------------------------------------------------------
1 | // Copyright(c) João Martiniano. All rights reserved.
2 | // Licensed under the MIT license.
3 |
4 | using System;
5 | using System.Collections.Generic;
6 | using System.ComponentModel;
7 | using System.Data;
8 | using System.Drawing;
9 | using System.Linq;
10 | using System.Text;
11 | using System.Threading.Tasks;
12 | using System.Windows.Forms;
13 |
14 | namespace MiniBug
15 | {
16 | public partial class AboutForm : Form
17 | {
18 | public AboutForm()
19 | {
20 | InitializeComponent();
21 | }
22 |
23 | private void AboutForm_Load(object sender, EventArgs e)
24 | {
25 | this.Text = "About MiniBug";
26 | this.AcceptButton = btOK;
27 |
28 | pictureBox1.Left = (lblApplicationName.Left / 2) - (pictureBox1.Width / 2);
29 |
30 | lblVersion.Text = $"Version {Application.ProductVersion.ToString()}";
31 | }
32 |
33 | ///
34 | /// Open a web browser when the user clicks on the link label.
35 | ///
36 | private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
37 | {
38 | System.Diagnostics.Process.Start(linkLabel1.Text);
39 | }
40 |
41 | ///
42 | /// Close this form.
43 | ///
44 | private void btOK_Click(object sender, EventArgs e)
45 | {
46 | this.Close();
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/MiniBug/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Resources;
2 | using System.Reflection;
3 | using System.Runtime.CompilerServices;
4 | using System.Runtime.InteropServices;
5 |
6 | // General Information about an assembly is controlled through the following
7 | // set of attributes. Change these attribute values to modify the information
8 | // associated with an assembly.
9 | [assembly: AssemblyTitle("MiniBug")]
10 | [assembly: AssemblyDescription("Issue Tracker and Todo List")]
11 | [assembly: AssemblyConfiguration("")]
12 | [assembly: AssemblyCompany("João Martiniano")]
13 | [assembly: AssemblyProduct("MiniBug")]
14 | [assembly: AssemblyCopyright("Copyright © 2019")]
15 | [assembly: AssemblyTrademark("")]
16 | [assembly: AssemblyCulture("")]
17 |
18 | // Setting ComVisible to false makes the types in this assembly not visible
19 | // to COM components. If you need to access a type in this assembly from
20 | // COM, set the ComVisible attribute to true on that type.
21 | [assembly: ComVisible(false)]
22 |
23 | // The following GUID is for the ID of the typelib if this project is exposed to COM
24 | [assembly: Guid("ef183892-a316-466b-b997-2ba7fad4db45")]
25 |
26 | // Version information for an assembly consists of the following four values:
27 | //
28 | // Major Version
29 | // Minor Version
30 | // Build Number
31 | // Revision
32 | //
33 | // You can specify all the values or you can default the Build and Revision Numbers
34 | // by using the '*' as shown below:
35 | // [assembly: AssemblyVersion("1.0.*")]
36 | [assembly: AssemblyVersion("1.0.0.0")]
37 | [assembly: AssemblyFileVersion("1.0.0.0")]
38 | [assembly: NeutralResourcesLanguage("")]
39 |
40 |
--------------------------------------------------------------------------------
/MiniBug/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | True
15 |
16 |
17 | 197, 197, 197
18 |
19 |
20 | 172, 212, 253
21 |
22 |
23 | Black
24 |
25 |
26 | Segoe UI, 8.25pt
27 |
28 |
29 | False
30 |
31 |
32 | White
33 |
34 |
35 | White
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/MiniBug/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | True
7 |
8 |
9 | 197, 197, 197
10 |
11 |
12 | 172, 212, 253
13 |
14 |
15 | Black
16 |
17 |
18 | Segoe UI, 8.25pt
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | False
28 |
29 |
30 | White
31 |
32 |
33 | White
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/MiniBug/Classes/GridTasksSortSettings.cs:
--------------------------------------------------------------------------------
1 | // Copyright(c) João Martiniano. All rights reserved.
2 | // Licensed under the MIT license.
3 |
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.Windows.Forms;
10 |
11 | namespace MiniBug
12 | {
13 | ///
14 | /// Sort settings for the tasks DataGridView.
15 | ///
16 | public class GridTasksSortSettings : IEquatable
17 | {
18 | ///
19 | /// First, sort by this column.
20 | ///
21 | public TaskFieldsUI FirstColumn { get; set; }
22 |
23 | ///
24 | /// Sort order for the first sort column.
25 | ///
26 | public SortOrder FirstColumnSortOrder { get; set; }
27 |
28 | ///
29 | /// Then, sort by this column.
30 | ///
31 | public TaskFieldsUI? SecondColumn { get; set; }
32 |
33 | ///
34 | /// Sort order for the second sort column.
35 | ///
36 | public SortOrder? SecondColumnSortOrder { get; set; }
37 |
38 | public GridTasksSortSettings(TaskFieldsUI firstColumn, SortOrder firstColumnSortOrder, TaskFieldsUI? secondColumn, SortOrder? secondColumnOrder)
39 | {
40 | FirstColumn = firstColumn;
41 | FirstColumnSortOrder = firstColumnSortOrder;
42 | SecondColumn = secondColumn;
43 | SecondColumnSortOrder = secondColumnOrder;
44 | }
45 |
46 | public override bool Equals(object obj)
47 | {
48 | return this.Equals(obj as GridTasksSortSettings);
49 | }
50 |
51 | public bool Equals(GridTasksSortSettings s)
52 | {
53 | // If parameter is null, return false.
54 | if (Object.ReferenceEquals(s, null))
55 | {
56 | return false;
57 | }
58 |
59 | // Optimization for a common success case.
60 | if (Object.ReferenceEquals(this, s))
61 | {
62 | return true;
63 | }
64 |
65 | // If run-time types are not exactly the same, return false.
66 | if (this.GetType() != s.GetType())
67 | {
68 | return false;
69 | }
70 |
71 | // Return true if all fields match.
72 | bool test1 = (FirstColumn == s.FirstColumn) && (FirstColumnSortOrder == s.FirstColumnSortOrder);
73 | bool test2 = (SecondColumn == s.SecondColumn) && (SecondColumnSortOrder == s.SecondColumnSortOrder);
74 |
75 | return test1 && test2;
76 | }
77 |
78 | public override int GetHashCode()
79 | {
80 | unchecked
81 | {
82 | int hash = 17;
83 | hash = hash * 23 + FirstColumn.GetHashCode();
84 | hash = hash * 23 + FirstColumnSortOrder.GetHashCode();
85 | hash = hash * 23 + ((SecondColumn == null) ? 0 : SecondColumn.GetHashCode());
86 | hash = hash * 23 + ((SecondColumnSortOrder == null) ? 0 : SecondColumnSortOrder.GetHashCode());
87 | return hash;
88 | }
89 | }
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/MiniBug/Classes/GridIssuesSortSettings.cs:
--------------------------------------------------------------------------------
1 | // Copyright(c) João Martiniano. All rights reserved.
2 | // Licensed under the MIT license.
3 |
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.Windows.Forms;
10 |
11 | namespace MiniBug
12 | {
13 | ///
14 | /// Sort settings for the issues DataGridView.
15 | ///
16 | public class GridIssuesSortSettings : IEquatable
17 | {
18 | ///
19 | /// First, sort by this column.
20 | ///
21 | public IssueFieldsUI FirstColumn { get; set; }
22 |
23 | ///
24 | /// Sort order for the first sort column.
25 | ///
26 | public SortOrder FirstColumnSortOrder { get; set; }
27 |
28 | ///
29 | /// Then, sort by this column.
30 | ///
31 | public IssueFieldsUI? SecondColumn { get; set; }
32 |
33 | ///
34 | /// Sort order for the second sort column.
35 | ///
36 | public SortOrder? SecondColumnSortOrder { get; set; }
37 |
38 | public GridIssuesSortSettings(IssueFieldsUI firstColumn, SortOrder firstColumnSortOrder, IssueFieldsUI? secondColumn, SortOrder? secondColumnOrder)
39 | {
40 | FirstColumn = firstColumn;
41 | FirstColumnSortOrder = firstColumnSortOrder;
42 | SecondColumn = secondColumn;
43 | SecondColumnSortOrder = secondColumnOrder;
44 | }
45 |
46 | public override bool Equals(object obj)
47 | {
48 | return this.Equals(obj as GridIssuesSortSettings);
49 | }
50 |
51 | public bool Equals(GridIssuesSortSettings s)
52 | {
53 | // If parameter is null, return false.
54 | if (Object.ReferenceEquals(s, null))
55 | {
56 | return false;
57 | }
58 |
59 | // Optimization for a common success case.
60 | if (Object.ReferenceEquals(this, s))
61 | {
62 | return true;
63 | }
64 |
65 | // If run-time types are not exactly the same, return false.
66 | if (this.GetType() != s.GetType())
67 | {
68 | return false;
69 | }
70 |
71 | // Return true if all fields match.
72 | bool test1 = (FirstColumn == s.FirstColumn) && (FirstColumnSortOrder == s.FirstColumnSortOrder);
73 | bool test2 = (SecondColumn == s.SecondColumn) && (SecondColumnSortOrder == s.SecondColumnSortOrder);
74 |
75 | return test1 && test2;
76 | }
77 |
78 | public override int GetHashCode()
79 | {
80 | unchecked
81 | {
82 | int hash = 17;
83 | hash = hash * 23 + FirstColumn.GetHashCode();
84 | hash = hash * 23 + FirstColumnSortOrder.GetHashCode();
85 | hash = hash * 23 + ((SecondColumn == null) ? 0 : SecondColumn.GetHashCode());
86 | hash = hash * 23 + ((SecondColumnSortOrder == null) ? 0 : SecondColumnSortOrder.GetHashCode());
87 | return hash;
88 | }
89 | }
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MiniBug - Issue Tracker and To-do List
2 |
3 | MiniBug is a barebones, simple issue tracker and to-do list. It is a Windows desktop single-user application.
4 |
5 |
6 |
7 | MiniBug does not use a database to store data: instead the application stores each project in a .json file. This means that if you need to work on projects, in different computers, you can share a MiniBug project between computers, by putting the .json file in something like Dropbox.
8 |
9 | ## Features
10 |
11 | - Issues: create, edit, delete, clone
12 | - Tasks: create, edit, delete, clone
13 | - Show/hide/sort columns
14 | - Some user defined settings
15 | - Export issues and tasks to CSV format
16 |
17 | ## Sample project
18 |
19 | I've made a small sample project, with bugs and tasks copied from some applications' public bug trackers (Inkscape, Firefox, MariaDB and Kodi).
20 |
21 | Download the file minibug-MiniBug Sample Project.json and open it in MiniBug.
22 |
23 | # Getting Started
24 |
25 | ## Prerequisites
26 |
27 | - Microsoft Windows 7 (maybe it works on older versions but I haven't tested)
28 | - Microsoft .NET Framework 4.6.1
29 |
30 | # How To Use
31 |
32 | First you need to create a new project (File > New Project), define a project name and choose a location to save it:
33 |
34 |
35 |
36 | Next you can start adding issues and tasks:
37 | - issues are bugs/problems
38 | - tasks are items in a to-do list
39 |
40 | ## Issues
41 |
42 |
43 |
44 |
45 | ## Tasks
46 |
47 |
48 |
49 | ## Settings
50 |
51 | The user can modify some settings (File > Settings) in order to customize the look and feel of the application:
52 |
53 |
54 |
55 | Settings in action:
56 |
57 |
58 |
59 | ## Sorting
60 |
61 | You can sort the grid rows in two ways:
62 |
63 | - by clicking on a column header:
64 |
65 |
66 |
67 | - by using the **Configure Columns** window:
68 |
69 |
70 |
71 | Using the second method you can sort by up to two columns and with different criteria (ascending or descending).
72 |
73 | ## Column visibility
74 |
75 | You can show/hide any column (except the **ID** column, which is always visible), using the **Configure Columns** window:
76 |
77 |
78 |
79 | ## Exporting
80 |
81 | You can export a project's issues and tasks to CSV (comma separated values) files:
82 |
83 |
84 |
85 | Because issues and tasks have a slightly different structure, they are exported to separate files. If a project only has issues or tasks, only one file will be generated:
86 |
87 |
88 |
89 | # License
90 |
91 | This project is licensed under the MIT License - see the LICENSE.md file for details.
92 |
93 | # Acknowledgments
94 |
95 | This project uses the following libraries:
96 |
97 | - Json.NET: for reading/writing to .json files
98 | - CsvHelper: for exporting to CSV
--------------------------------------------------------------------------------
/MiniBug/Classes/ImportExportResult.cs:
--------------------------------------------------------------------------------
1 | // Copyright(c) João Martiniano. All rights reserved.
2 | // Licensed under the MIT license.
3 |
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 |
10 | namespace MiniBug
11 | {
12 | public enum ImportExportOperation { None = 0, Import, Export }
13 |
14 | ///
15 | /// Detail information about a specific import/export operation.
16 | ///
17 | public class ImportExportResultData
18 | {
19 | public string FileName { get; set; } = string.Empty;
20 |
21 | public string Path { get; set; } = string.Empty;
22 |
23 | private FileSystemOperationStatus _result;
24 |
25 | public FileSystemOperationStatus Result
26 | {
27 | get { return _result; }
28 | set { _result = value; ComposeMessage(); }
29 | }
30 |
31 | public string ResultMessage { get; set; } = string.Empty;
32 |
33 | public string ResultDescription { get; set; } = string.Empty;
34 |
35 | public string ResultSolution { get; set; } = string.Empty;
36 |
37 | private void ComposeMessage()
38 | {
39 | switch (Result)
40 | {
41 | case FileSystemOperationStatus.ExportOK:
42 | ResultMessage = "Export successful";
43 | break;
44 |
45 | case FileSystemOperationStatus.ExportToCsvErrorDirectoryNotFound:
46 | ResultMessage = "Location not found";
47 | ResultDescription = "The specified location does not exist.";
48 | ResultSolution = "Choose a different location.";
49 | break;
50 |
51 | case FileSystemOperationStatus.ExportToCsvErrorPathTooLong:
52 | ResultMessage = "Path too long";
53 | ResultDescription = "The path, file name or both are too long.";
54 | ResultSolution = "Choose a different location and/or a shorter filename.";
55 | break;
56 |
57 | case FileSystemOperationStatus.ExportToCsvErrorExporterComponent:
58 | ResultMessage = "Component error";
59 | ResultDescription = "The component responsible for exporting the project has failed.";
60 | ResultSolution = "Please try again.";
61 | break;
62 |
63 | case FileSystemOperationStatus.ExportToCsvIOError:
64 | ResultMessage = "I/O Error";
65 | ResultDescription = "There was a general input/output error while attempting to export.";
66 | ResultSolution = "Choose a different drive/device to export the project.";
67 | break;
68 |
69 | default:
70 | ResultMessage = string.Empty;
71 | ResultDescription = string.Empty;
72 | ResultSolution = string.Empty;
73 | break;
74 | }
75 | }
76 | }
77 |
78 | ///
79 | /// Result of an import/export operation. Contains details about the import/export operation.
80 | ///
81 | public class ImportExportResult
82 | {
83 | public ImportExportOperation Operation { get; set; } = ImportExportOperation.None;
84 |
85 | public ImportExportResultData Issues { get; set; } = null;
86 |
87 | public ImportExportResultData Tasks { get; set; } = null;
88 |
89 | public ImportExportResult(ImportExportOperation operation)
90 | {
91 | Operation = operation;
92 |
93 | Issues = new ImportExportResultData();
94 | Tasks = new ImportExportResultData();
95 | }
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/MiniBug/Classes/Task.cs:
--------------------------------------------------------------------------------
1 | // Copyright(c) João Martiniano. All rights reserved.
2 | // Licensed under the MIT license.
3 |
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.ComponentModel;
10 |
11 | namespace MiniBug
12 | {
13 | ///
14 | /// Status of a task.
15 | ///
16 | public enum TaskStatus
17 | {
18 | None = 0,
19 | [DescriptionAttribute("Not started")]
20 | NotStarted,
21 | [DescriptionAttribute("In progress")]
22 | InProgress,
23 | Finished
24 | };
25 |
26 | ///
27 | /// Priority of a task.
28 | ///
29 | public enum TaskPriority { None = 0, Low, Normal, High, Urgent, Immediate };
30 |
31 | ///
32 | /// Fields used on the user interface (in a DataGridView and on a form) to represent a task.
33 | ///
34 | public enum TaskFieldsUI
35 | {
36 | ID = 0,
37 | Priority,
38 | Status,
39 | TargetVersion,
40 | [DescriptionAttribute("Date created")]
41 | Summary,
42 | Description,
43 | [DescriptionAttribute("Target version")]
44 | DateCreated,
45 | [DescriptionAttribute("Date modified")]
46 | DateModified
47 | };
48 |
49 | [Serializable]
50 | public class Task
51 | {
52 | ///
53 | /// Gets the ID of this task.
54 | ///
55 | public int ID { get; set; }
56 |
57 | ///
58 | /// Gets or sets the priority of this task.
59 | ///
60 | public TaskPriority Priority { get; set; }
61 |
62 | ///
63 | /// Gets or sets the status of this task.
64 | ///
65 | public TaskStatus Status { get; set; }
66 |
67 | ///
68 | /// Gets or sets the future version on which this task will be applied/finished.
69 | ///
70 | public string TargetVersion { get; set; }
71 |
72 | ///
73 | /// Gets or sets the summary of this task.
74 | ///
75 | public string Summary { get; set; }
76 |
77 | ///
78 | /// Gets or sets the description of this task.
79 | ///
80 | public string Description { get; set; }
81 |
82 | ///
83 | /// Gets or sets the date/time this task was created.
84 | ///
85 | public DateTime DateCreated { get; set; }
86 |
87 | ///
88 | /// Gets or sets the date/time this task was modified.
89 | ///
90 | public DateTime DateModified { get; set; }
91 |
92 | ///
93 | /// Creates a new task.
94 | ///
95 | public Task()
96 | {
97 | ;
98 | }
99 |
100 | ///
101 | /// Creates a new task.
102 | ///
103 | /// The ID of this task.
104 | public Task(int id)
105 | {
106 | ID = id;
107 | }
108 |
109 | ///
110 | /// Creates a new task.
111 | ///
112 | public Task(TaskStatus status, TaskPriority priority, string summary, string description, string targetVersion)
113 | {
114 | Status = status;
115 | Priority = priority;
116 | Summary = summary;
117 | Description = description;
118 | TargetVersion = targetVersion;
119 |
120 | DateCreated = DateTime.Now;
121 | DateModified = DateTime.Now;
122 | }
123 |
124 | ///
125 | /// Create a clone of an instance of the Task class.
126 | ///
127 | /// The instance of the Task class that will get the cloned instance's data.
128 | public void Clone(ref Task clonedInstance)
129 | {
130 | clonedInstance.Status = this.Status;
131 | clonedInstance.Priority = this.Priority;
132 | clonedInstance.Summary = this.Summary;
133 | clonedInstance.Description = this.Description;
134 | clonedInstance.TargetVersion = this.TargetVersion;
135 | clonedInstance.DateCreated = clonedInstance.DateModified = DateTime.Now;
136 | }
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/MiniBug/Classes/Issue.cs:
--------------------------------------------------------------------------------
1 | // Copyright(c) João Martiniano. All rights reserved.
2 | // Licensed under the MIT license.
3 |
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.ComponentModel;
10 |
11 | namespace MiniBug
12 | {
13 | ///
14 | /// Status of an issue.
15 | ///
16 | public enum IssueStatus
17 | {
18 | None = 0,
19 | Unconfirmed,
20 | Confirmed,
21 | [DescriptionAttribute("In progress")]
22 | InProgress,
23 | Resolved,
24 | Closed
25 | };
26 |
27 | ///
28 | /// Priority of an issue.
29 | ///
30 | public enum IssuePriority { None = 0, Low, Normal, High, Urgent, Immediate };
31 |
32 | ///
33 | /// Fields used on the user interface (in a DataGridView and on a form) to represent an issue.
34 | ///
35 | public enum IssueFieldsUI
36 | {
37 | ID = 0,
38 | Priority,
39 | Status,
40 | Version,
41 | [DescriptionAttribute("Target version")]
42 | TargetVersion,
43 | Summary,
44 | Description,
45 | [DescriptionAttribute("Date created")]
46 | DateCreated,
47 | [DescriptionAttribute("Date modified")]
48 | DateModified
49 | };
50 |
51 | [Serializable]
52 | public class Issue
53 | {
54 | ///
55 | /// Gets the ID of this issue.
56 | ///
57 | public int ID { get; set; } = 0;
58 |
59 | ///
60 | /// Gets or sets the priority of this issue.
61 | ///
62 | public IssuePriority Priority { get; set; } = IssuePriority.None;
63 |
64 | ///
65 | /// Gets or sets the status of this issue.
66 | ///
67 | public IssueStatus Status { get; set; } = IssueStatus.None;
68 |
69 | ///
70 | /// Gets or sets the version of the software on which this issue occurs.
71 | ///
72 | public string Version { get; set; } = string.Empty;
73 |
74 | ///
75 | /// Gets or sets the future version on which this issue will be resolved.
76 | ///
77 | public string TargetVersion { get; set; } = string.Empty;
78 |
79 | ///
80 | /// Gets or sets the summary of this issue.
81 | ///
82 | public string Summary { get; set; } = string.Empty;
83 |
84 | ///
85 | /// Gets or sets the description of this issue.
86 | ///
87 | public string Description { get; set; } = string.Empty;
88 |
89 | ///
90 | /// Gets or sets the date/time this issue was created.
91 | ///
92 | public DateTime DateCreated { get; set; }
93 |
94 | ///
95 | /// Gets or sets the date/time this issue was modified.
96 | ///
97 | public DateTime DateModified { get; set; }
98 |
99 | ///
100 | /// Creates a new issue.
101 | ///
102 | public Issue()
103 | {
104 | ;
105 | }
106 |
107 | ///
108 | /// Creates a new issue.
109 | ///
110 | /// The ID of this issue.
111 | public Issue(int id)
112 | {
113 | ID = id;
114 |
115 | DateCreated = DateTime.Now;
116 | DateModified = DateTime.Now;
117 | }
118 |
119 | ///
120 | /// Creates a new issue.
121 | ///
122 | public Issue(IssueStatus status, IssuePriority priority, string summary, string description, string version, string targetVersion)
123 | {
124 | Status = status;
125 | Priority = priority;
126 | Summary = summary;
127 | Description = description;
128 | Version = version;
129 | TargetVersion = targetVersion;
130 |
131 | DateCreated = DateTime.Now;
132 | DateModified = DateTime.Now;
133 | }
134 |
135 | ///
136 | /// Create a clone of an instance of the Issue class.
137 | ///
138 | /// The instance of the Issue class that will get the cloned instance's data.
139 | public void Clone(ref Issue clonedInstance)
140 | {
141 | clonedInstance.Status = this.Status;
142 | clonedInstance.Priority = this.Priority;
143 | clonedInstance.Summary = this.Summary;
144 | clonedInstance.Description = this.Description;
145 | clonedInstance.Version = this.Version;
146 | clonedInstance.TargetVersion = this.TargetVersion;
147 | clonedInstance.DateCreated = clonedInstance.DateModified = DateTime.Now;
148 | }
149 | }
150 | }
151 |
--------------------------------------------------------------------------------
/MiniBug/FeedbackForm.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace MiniBug
2 | {
3 | partial class FeedbackForm
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | this.btClose = new System.Windows.Forms.Button();
32 | this.lblMessageTitle = new System.Windows.Forms.Label();
33 | this.lblMessage = new System.Windows.Forms.Label();
34 | this.pictureBox1 = new System.Windows.Forms.PictureBox();
35 | ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
36 | this.SuspendLayout();
37 | //
38 | // btClose
39 | //
40 | this.btClose.Location = new System.Drawing.Point(621, 228);
41 | this.btClose.Name = "btClose";
42 | this.btClose.Size = new System.Drawing.Size(75, 23);
43 | this.btClose.TabIndex = 0;
44 | this.btClose.Text = "Close";
45 | this.btClose.UseVisualStyleBackColor = true;
46 | this.btClose.Click += new System.EventHandler(this.btClose_Click);
47 | //
48 | // lblMessageTitle
49 | //
50 | this.lblMessageTitle.AutoEllipsis = true;
51 | this.lblMessageTitle.Font = new System.Drawing.Font("Segoe UI", 18F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
52 | this.lblMessageTitle.Location = new System.Drawing.Point(91, 23);
53 | this.lblMessageTitle.Name = "lblMessageTitle";
54 | this.lblMessageTitle.Size = new System.Drawing.Size(605, 32);
55 | this.lblMessageTitle.TabIndex = 1;
56 | this.lblMessageTitle.Text = "MessageTitle";
57 | //
58 | // lblMessage
59 | //
60 | this.lblMessage.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
61 | this.lblMessage.Location = new System.Drawing.Point(94, 75);
62 | this.lblMessage.Name = "lblMessage";
63 | this.lblMessage.Size = new System.Drawing.Size(583, 126);
64 | this.lblMessage.TabIndex = 2;
65 | this.lblMessage.Text = "Message";
66 | //
67 | // pictureBox1
68 | //
69 | this.pictureBox1.Location = new System.Drawing.Point(12, 23);
70 | this.pictureBox1.Name = "pictureBox1";
71 | this.pictureBox1.Size = new System.Drawing.Size(64, 64);
72 | this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage;
73 | this.pictureBox1.TabIndex = 3;
74 | this.pictureBox1.TabStop = false;
75 | //
76 | // FeedbackForm
77 | //
78 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
79 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
80 | this.ClientSize = new System.Drawing.Size(708, 263);
81 | this.Controls.Add(this.pictureBox1);
82 | this.Controls.Add(this.lblMessage);
83 | this.Controls.Add(this.lblMessageTitle);
84 | this.Controls.Add(this.btClose);
85 | this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
86 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
87 | this.MaximizeBox = false;
88 | this.MinimizeBox = false;
89 | this.Name = "FeedbackForm";
90 | this.ShowIcon = false;
91 | this.ShowInTaskbar = false;
92 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
93 | this.Text = "FeedbackForm";
94 | this.Load += new System.EventHandler(this.FeedbackForm_Load);
95 | ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
96 | this.ResumeLayout(false);
97 |
98 | }
99 |
100 | #endregion
101 |
102 | private System.Windows.Forms.Button btClose;
103 | private System.Windows.Forms.Label lblMessageTitle;
104 | private System.Windows.Forms.Label lblMessage;
105 | private System.Windows.Forms.PictureBox pictureBox1;
106 | }
107 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | x64/
19 | x86/
20 | bld/
21 | [Bb]in/
22 | [Oo]bj/
23 | [Ll]og/
24 |
25 | # Visual Studio 2015 cache/options directory
26 | .vs/
27 | # Uncomment if you have tasks that create the project's static files in wwwroot
28 | #wwwroot/
29 |
30 | # MSTest test Results
31 | [Tt]est[Rr]esult*/
32 | [Bb]uild[Ll]og.*
33 |
34 | # NUNIT
35 | *.VisualState.xml
36 | TestResult.xml
37 |
38 | # Build Results of an ATL Project
39 | [Dd]ebugPS/
40 | [Rr]eleasePS/
41 | dlldata.c
42 |
43 | # DNX
44 | project.lock.json
45 | project.fragment.lock.json
46 | artifacts/
47 |
48 | *_i.c
49 | *_p.c
50 | *_i.h
51 | *.ilk
52 | *.meta
53 | *.obj
54 | *.pch
55 | *.pdb
56 | *.pgc
57 | *.pgd
58 | *.rsp
59 | *.sbr
60 | *.tlb
61 | *.tli
62 | *.tlh
63 | *.tmp
64 | *.tmp_proj
65 | *.log
66 | *.vspscc
67 | *.vssscc
68 | .builds
69 | *.pidb
70 | *.svclog
71 | *.scc
72 |
73 | # Chutzpah Test files
74 | _Chutzpah*
75 |
76 | # Visual C++ cache files
77 | ipch/
78 | *.aps
79 | *.ncb
80 | *.opendb
81 | *.opensdf
82 | *.sdf
83 | *.cachefile
84 | *.VC.db
85 | *.VC.VC.opendb
86 |
87 | # Visual Studio profiler
88 | *.psess
89 | *.vsp
90 | *.vspx
91 | *.sap
92 |
93 | # TFS 2012 Local Workspace
94 | $tf/
95 |
96 | # Guidance Automation Toolkit
97 | *.gpState
98 |
99 | # ReSharper is a .NET coding add-in
100 | _ReSharper*/
101 | *.[Rr]e[Ss]harper
102 | *.DotSettings.user
103 |
104 | # JustCode is a .NET coding add-in
105 | .JustCode
106 |
107 | # TeamCity is a build add-in
108 | _TeamCity*
109 |
110 | # DotCover is a Code Coverage Tool
111 | *.dotCover
112 |
113 | # NCrunch
114 | _NCrunch_*
115 | .*crunch*.local.xml
116 | nCrunchTemp_*
117 |
118 | # MightyMoose
119 | *.mm.*
120 | AutoTest.Net/
121 |
122 | # Web workbench (sass)
123 | .sass-cache/
124 |
125 | # Installshield output folder
126 | [Ee]xpress/
127 |
128 | # DocProject is a documentation generator add-in
129 | DocProject/buildhelp/
130 | DocProject/Help/*.HxT
131 | DocProject/Help/*.HxC
132 | DocProject/Help/*.hhc
133 | DocProject/Help/*.hhk
134 | DocProject/Help/*.hhp
135 | DocProject/Help/Html2
136 | DocProject/Help/html
137 |
138 | # Click-Once directory
139 | publish/
140 |
141 | # Publish Web Output
142 | *.[Pp]ublish.xml
143 | *.azurePubxml
144 | # TODO: Comment the next line if you want to checkin your web deploy settings
145 | # but database connection strings (with potential passwords) will be unencrypted
146 | #*.pubxml
147 | *.publishproj
148 |
149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
150 | # checkin your Azure Web App publish settings, but sensitive information contained
151 | # in these scripts will be unencrypted
152 | PublishScripts/
153 |
154 | # NuGet Packages
155 | *.nupkg
156 | # The packages folder can be ignored because of Package Restore
157 | **/packages/*
158 | # except build/, which is used as an MSBuild target.
159 | !**/packages/build/
160 | # Uncomment if necessary however generally it will be regenerated when needed
161 | #!**/packages/repositories.config
162 | # NuGet v3's project.json files produces more ignoreable files
163 | *.nuget.props
164 | *.nuget.targets
165 |
166 | # Microsoft Azure Build Output
167 | csx/
168 | *.build.csdef
169 |
170 | # Microsoft Azure Emulator
171 | ecf/
172 | rcf/
173 |
174 | # Windows Store app package directories and files
175 | AppPackages/
176 | BundleArtifacts/
177 | Package.StoreAssociation.xml
178 | _pkginfo.txt
179 |
180 | # Visual Studio cache files
181 | # files ending in .cache can be ignored
182 | *.[Cc]ache
183 | # but keep track of directories ending in .cache
184 | !*.[Cc]ache/
185 |
186 | # Others
187 | ClientBin/
188 | ~$*
189 | *~
190 | *.dbmdl
191 | *.dbproj.schemaview
192 | *.jfm
193 | *.pfx
194 | *.publishsettings
195 | node_modules/
196 | orleans.codegen.cs
197 |
198 | # Since there are multiple workflows, uncomment next line to ignore bower_components
199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
200 | #bower_components/
201 |
202 | # RIA/Silverlight projects
203 | Generated_Code/
204 |
205 | # Backup & report files from converting an old project file
206 | # to a newer Visual Studio version. Backup files are not needed,
207 | # because we have git ;-)
208 | _UpgradeReport_Files/
209 | Backup*/
210 | UpgradeLog*.XML
211 | UpgradeLog*.htm
212 |
213 | # SQL Server files
214 | *.mdf
215 | *.ldf
216 |
217 | # Business Intelligence projects
218 | *.rdl.data
219 | *.bim.layout
220 | *.bim_*.settings
221 |
222 | # Microsoft Fakes
223 | FakesAssemblies/
224 |
225 | # GhostDoc plugin setting file
226 | *.GhostDoc.xml
227 |
228 | # Node.js Tools for Visual Studio
229 | .ntvs_analysis.dat
230 |
231 | # Visual Studio 6 build log
232 | *.plg
233 |
234 | # Visual Studio 6 workspace options file
235 | *.opt
236 |
237 | # Visual Studio LightSwitch build output
238 | **/*.HTMLClient/GeneratedArtifacts
239 | **/*.DesktopClient/GeneratedArtifacts
240 | **/*.DesktopClient/ModelManifest.xml
241 | **/*.Server/GeneratedArtifacts
242 | **/*.Server/ModelManifest.xml
243 | _Pvt_Extensions
244 |
245 | # Paket dependency manager
246 | .paket/paket.exe
247 | paket-files/
248 |
249 | # FAKE - F# Make
250 | .fake/
251 |
252 | # JetBrains Rider
253 | .idea/
254 | *.sln.iml
255 |
256 | # CodeRush
257 | .cr/
258 |
259 | # Python Tools for Visual Studio (PTVS)
260 | __pycache__/
261 | *.pyc
--------------------------------------------------------------------------------
/MiniBug/ProjectForm.cs:
--------------------------------------------------------------------------------
1 | // Copyright(c) João Martiniano. All rights reserved.
2 | // Licensed under the MIT license.
3 |
4 | using System;
5 | using System.Collections.Generic;
6 | using System.ComponentModel;
7 | using System.Data;
8 | using System.Drawing;
9 | using System.Linq;
10 | using System.Text;
11 | using System.Threading.Tasks;
12 | using System.Windows.Forms;
13 | using System.IO;
14 |
15 | namespace MiniBug
16 | {
17 | public partial class ProjectForm : Form
18 | {
19 | ///
20 | /// Gets the current operation.
21 | ///
22 | public MiniBug.OperationType Operation { get; private set; } = OperationType.None;
23 |
24 | ///
25 | /// Gets the name of the project.
26 | ///
27 | public string ProjectName { get; private set; } = string.Empty;
28 |
29 | ///
30 | /// Gets the name of the project file.
31 | ///
32 | public string ProjectFilename { get; private set; } = string.Empty;
33 |
34 | ///
35 | /// Gets the location of the project file.
36 | ///
37 | public string ProjectLocation { get; private set; } = string.Empty;
38 |
39 | public ProjectForm(OperationType operation, string projectName = "", string projectFilename = "", string projectLocation = "")
40 | {
41 | InitializeComponent();
42 |
43 | Operation = operation;
44 |
45 | if (Operation == OperationType.Edit)
46 | {
47 | // Edit an existing project
48 | ProjectName = projectName;
49 | ProjectFilename = projectFilename;
50 | ProjectLocation = projectLocation;
51 | }
52 | }
53 |
54 | private void ProjectForm_Load(object sender, EventArgs e)
55 | {
56 | // Suspend the layout logic for the form, while the application is initializing
57 | this.SuspendLayout();
58 |
59 | this.AcceptButton = btOk;
60 | this.CancelButton = btCancel;
61 |
62 | lblFormTitle.Width = this.ClientRectangle.Width;
63 |
64 | txtName.MaxLength = 255;
65 |
66 | // Make initializations based on the type of operation
67 | if (Operation == OperationType.New)
68 | {
69 | this.Text = "New Project";
70 | lblFormTitle.Text = "Create a new project";
71 |
72 | btOk.Enabled = false;
73 | }
74 | else if (Operation == OperationType.Edit)
75 | {
76 | this.Text = "Edit Project";
77 | lblFormTitle.Text = "Edit the current project";
78 |
79 | // Populate the controls
80 | txtName.Text = ProjectName;
81 | txtFilename.Text = ProjectFilename;
82 | txtLocation.Text = ProjectLocation;
83 | }
84 |
85 | // Resume the layout logic
86 | this.ResumeLayout();
87 |
88 | SetAccessibilityInformation();
89 | }
90 |
91 | ///
92 | /// Add accessibility data to form controls.
93 | ///
94 | private void SetAccessibilityInformation()
95 | {
96 | txtFilename.AccessibleDescription = "The name of the file containing the project";
97 | txtLocation.AccessibleDescription = "Folder where the project file will be saved";
98 | btBrowse.AccessibleDescription = "Browse for the folder where the project file will be saved";
99 | }
100 |
101 | ///
102 | /// Browse the location where the project will be saved.
103 | ///
104 | private void btBrowse_Click(object sender, EventArgs e)
105 | {
106 | if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
107 | {
108 | txtLocation.Text = folderBrowserDialog1.SelectedPath;
109 |
110 | if (txtName.Text != string.Empty)
111 | {
112 | btOk.Enabled = true;
113 | }
114 | }
115 | }
116 |
117 | ///
118 | /// Close the form.
119 | ///
120 | private void btOk_Click(object sender, EventArgs e)
121 | {
122 | if ((!string.IsNullOrWhiteSpace(txtName.Text)) && (!string.IsNullOrWhiteSpace(txtLocation.Text)))
123 | {
124 | ProjectName = txtName.Text;
125 | ProjectFilename = txtFilename.Text;
126 | ProjectLocation = txtLocation.Text;
127 |
128 | this.DialogResult = DialogResult.OK;
129 | this.Close();
130 | }
131 | }
132 |
133 | ///
134 | /// Cancel this operation and close the form.
135 | ///
136 | private void btCancel_Click(object sender, EventArgs e)
137 | {
138 | this.DialogResult = DialogResult.Cancel;
139 | this.Close();
140 | }
141 |
142 | ///
143 | /// Handle the TextChanged event for the project name textbox control.
144 | ///
145 | private void txtName_TextChanged(object sender, EventArgs e)
146 | {
147 | if (!string.IsNullOrWhiteSpace(txtName.Text))
148 | {
149 | txtFilename.Text = $"minibug-{txtName.Text}.json";
150 |
151 | if (txtLocation.Text != string.Empty)
152 | {
153 | btOk.Enabled = true;
154 | }
155 | }
156 | else
157 | {
158 | txtFilename.Text = string.Empty;
159 | btOk.Enabled = false;
160 | }
161 | }
162 | }
163 | }
164 |
--------------------------------------------------------------------------------
/MiniBug/IssueForm.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
--------------------------------------------------------------------------------
/MiniBug/TaskForm.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
--------------------------------------------------------------------------------
/MiniBug/FeedbackForm.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
--------------------------------------------------------------------------------
/MiniBug/ConfigureViewForm.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
--------------------------------------------------------------------------------
/MiniBug/ImportExportFeedbackForm.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
--------------------------------------------------------------------------------
/MiniBug/SettingsForm.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | 17, 17
122 |
123 |
--------------------------------------------------------------------------------
/MiniBug/ExportForm.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | 17, 17
122 |
123 |
--------------------------------------------------------------------------------
/MiniBug/ProjectForm.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | 17, 17
122 |
123 |
--------------------------------------------------------------------------------
/MiniBug/AboutForm.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace MiniBug
2 | {
3 | partial class AboutForm
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(AboutForm));
32 | this.btOK = new System.Windows.Forms.Button();
33 | this.lblApplicationName = new System.Windows.Forms.Label();
34 | this.pictureBox1 = new System.Windows.Forms.PictureBox();
35 | this.lblVersion = new System.Windows.Forms.Label();
36 | this.label2 = new System.Windows.Forms.Label();
37 | this.linkLabel1 = new System.Windows.Forms.LinkLabel();
38 | ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
39 | this.SuspendLayout();
40 | //
41 | // btOK
42 | //
43 | this.btOK.Location = new System.Drawing.Point(315, 146);
44 | this.btOK.Name = "btOK";
45 | this.btOK.Size = new System.Drawing.Size(75, 23);
46 | this.btOK.TabIndex = 0;
47 | this.btOK.Text = "OK";
48 | this.btOK.UseVisualStyleBackColor = true;
49 | this.btOK.Click += new System.EventHandler(this.btOK_Click);
50 | //
51 | // lblApplicationName
52 | //
53 | this.lblApplicationName.AutoSize = true;
54 | this.lblApplicationName.Font = new System.Drawing.Font("Microsoft Sans Serif", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
55 | this.lblApplicationName.Location = new System.Drawing.Point(107, 12);
56 | this.lblApplicationName.Name = "lblApplicationName";
57 | this.lblApplicationName.Size = new System.Drawing.Size(197, 24);
58 | this.lblApplicationName.TabIndex = 1;
59 | this.lblApplicationName.Text = "MiniBug Issue Tracker";
60 | //
61 | // pictureBox1
62 | //
63 | this.pictureBox1.Image = ((System.Drawing.Image)(resources.GetObject("pictureBox1.Image")));
64 | this.pictureBox1.Location = new System.Drawing.Point(20, 12);
65 | this.pictureBox1.Name = "pictureBox1";
66 | this.pictureBox1.Size = new System.Drawing.Size(64, 64);
67 | this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize;
68 | this.pictureBox1.TabIndex = 2;
69 | this.pictureBox1.TabStop = false;
70 | //
71 | // lblVersion
72 | //
73 | this.lblVersion.AutoSize = true;
74 | this.lblVersion.Location = new System.Drawing.Point(107, 52);
75 | this.lblVersion.Name = "lblVersion";
76 | this.lblVersion.Size = new System.Drawing.Size(46, 13);
77 | this.lblVersion.TabIndex = 3;
78 | this.lblVersion.Text = "Version";
79 | //
80 | // label2
81 | //
82 | this.label2.AutoSize = true;
83 | this.label2.Location = new System.Drawing.Point(107, 81);
84 | this.label2.Name = "label2";
85 | this.label2.Size = new System.Drawing.Size(192, 13);
86 | this.label2.TabIndex = 4;
87 | this.label2.Text = "Copyright © 2019 - João Martiniano";
88 | //
89 | // linkLabel1
90 | //
91 | this.linkLabel1.AutoSize = true;
92 | this.linkLabel1.Location = new System.Drawing.Point(107, 110);
93 | this.linkLabel1.Name = "linkLabel1";
94 | this.linkLabel1.Size = new System.Drawing.Size(265, 13);
95 | this.linkLabel1.TabIndex = 5;
96 | this.linkLabel1.TabStop = true;
97 | this.linkLabel1.Text = "https://www.github.com/joaomartiniano/MiniBug";
98 | this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked);
99 | //
100 | // AboutForm
101 | //
102 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
103 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
104 | this.ClientSize = new System.Drawing.Size(402, 181);
105 | this.Controls.Add(this.linkLabel1);
106 | this.Controls.Add(this.label2);
107 | this.Controls.Add(this.lblVersion);
108 | this.Controls.Add(this.pictureBox1);
109 | this.Controls.Add(this.lblApplicationName);
110 | this.Controls.Add(this.btOK);
111 | this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
112 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
113 | this.MaximizeBox = false;
114 | this.MinimizeBox = false;
115 | this.Name = "AboutForm";
116 | this.ShowInTaskbar = false;
117 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
118 | this.Text = "AboutForm";
119 | this.Load += new System.EventHandler(this.AboutForm_Load);
120 | ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
121 | this.ResumeLayout(false);
122 | this.PerformLayout();
123 |
124 | }
125 |
126 | #endregion
127 |
128 | private System.Windows.Forms.Button btOK;
129 | private System.Windows.Forms.Label lblApplicationName;
130 | private System.Windows.Forms.PictureBox pictureBox1;
131 | private System.Windows.Forms.Label lblVersion;
132 | private System.Windows.Forms.Label label2;
133 | private System.Windows.Forms.LinkLabel linkLabel1;
134 | }
135 | }
--------------------------------------------------------------------------------
/MiniBug/MainForm.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | 17, 17
122 |
123 |
124 | 122, 17
125 |
126 |
127 | 237, 17
128 |
129 |
--------------------------------------------------------------------------------
/MiniBug/ImportExportFeedbackForm.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace MiniBug
2 | {
3 | partial class ImportExportFeedbackForm
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | this.lblFormTitle = new System.Windows.Forms.Label();
32 | this.btClose = new System.Windows.Forms.Button();
33 | this.IconDescription = new System.Windows.Forms.PictureBox();
34 | this.lblDescription = new System.Windows.Forms.Label();
35 | this.label1 = new System.Windows.Forms.Label();
36 | this.FlowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel();
37 | ((System.ComponentModel.ISupportInitialize)(this.IconDescription)).BeginInit();
38 | this.SuspendLayout();
39 | //
40 | // lblFormTitle
41 | //
42 | this.lblFormTitle.BackColor = System.Drawing.Color.White;
43 | this.lblFormTitle.Font = new System.Drawing.Font("Segoe UI", 18F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
44 | this.lblFormTitle.Location = new System.Drawing.Point(0, 0);
45 | this.lblFormTitle.Name = "lblFormTitle";
46 | this.lblFormTitle.Padding = new System.Windows.Forms.Padding(10, 0, 0, 0);
47 | this.lblFormTitle.Size = new System.Drawing.Size(609, 63);
48 | this.lblFormTitle.TabIndex = 2;
49 | this.lblFormTitle.Text = "Export Project to CSV";
50 | this.lblFormTitle.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
51 | //
52 | // btClose
53 | //
54 | this.btClose.Location = new System.Drawing.Point(517, 342);
55 | this.btClose.Name = "btClose";
56 | this.btClose.Size = new System.Drawing.Size(75, 23);
57 | this.btClose.TabIndex = 3;
58 | this.btClose.Text = "Close";
59 | this.btClose.UseVisualStyleBackColor = true;
60 | this.btClose.Click += new System.EventHandler(this.btClose_Click);
61 | //
62 | // IconDescription
63 | //
64 | this.IconDescription.Location = new System.Drawing.Point(17, 85);
65 | this.IconDescription.Name = "IconDescription";
66 | this.IconDescription.Size = new System.Drawing.Size(16, 16);
67 | this.IconDescription.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize;
68 | this.IconDescription.TabIndex = 13;
69 | this.IconDescription.TabStop = false;
70 | //
71 | // lblDescription
72 | //
73 | this.lblDescription.AutoSize = true;
74 | this.lblDescription.Location = new System.Drawing.Point(35, 87);
75 | this.lblDescription.Name = "lblDescription";
76 | this.lblDescription.Size = new System.Drawing.Size(66, 13);
77 | this.lblDescription.TabIndex = 14;
78 | this.lblDescription.Text = "Description";
79 | //
80 | // label1
81 | //
82 | this.label1.AutoSize = true;
83 | this.label1.Location = new System.Drawing.Point(14, 118);
84 | this.label1.Name = "label1";
85 | this.label1.Size = new System.Drawing.Size(45, 13);
86 | this.label1.TabIndex = 15;
87 | this.label1.Text = "&Details:";
88 | //
89 | // FlowLayoutPanel1
90 | //
91 | this.FlowLayoutPanel1.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
92 | this.FlowLayoutPanel1.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
93 | this.FlowLayoutPanel1.Location = new System.Drawing.Point(17, 136);
94 | this.FlowLayoutPanel1.Name = "FlowLayoutPanel1";
95 | this.FlowLayoutPanel1.Padding = new System.Windows.Forms.Padding(0, 2, 0, 2);
96 | this.FlowLayoutPanel1.Size = new System.Drawing.Size(575, 188);
97 | this.FlowLayoutPanel1.TabIndex = 16;
98 | //
99 | // ImportExportFeedbackForm
100 | //
101 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
102 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
103 | this.ClientSize = new System.Drawing.Size(609, 377);
104 | this.Controls.Add(this.FlowLayoutPanel1);
105 | this.Controls.Add(this.label1);
106 | this.Controls.Add(this.lblDescription);
107 | this.Controls.Add(this.IconDescription);
108 | this.Controls.Add(this.btClose);
109 | this.Controls.Add(this.lblFormTitle);
110 | this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
111 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
112 | this.MaximizeBox = false;
113 | this.MinimizeBox = false;
114 | this.Name = "ImportExportFeedbackForm";
115 | this.ShowIcon = false;
116 | this.ShowInTaskbar = false;
117 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
118 | this.Text = "ImportExportFeedbackForm";
119 | this.Load += new System.EventHandler(this.ImportExportFeedbackForm_Load);
120 | ((System.ComponentModel.ISupportInitialize)(this.IconDescription)).EndInit();
121 | this.ResumeLayout(false);
122 | this.PerformLayout();
123 |
124 | }
125 |
126 | #endregion
127 |
128 | private System.Windows.Forms.Label lblFormTitle;
129 | private System.Windows.Forms.Button btClose;
130 | private System.Windows.Forms.PictureBox IconDescription;
131 | private System.Windows.Forms.Label lblDescription;
132 | private System.Windows.Forms.Label label1;
133 | private System.Windows.Forms.FlowLayoutPanel FlowLayoutPanel1;
134 | }
135 | }
--------------------------------------------------------------------------------
/MiniBug/Classes/TasksDataGridViewRowComparer.cs:
--------------------------------------------------------------------------------
1 | // Copyright(c) João Martiniano. All rights reserved.
2 | // Licensed under the MIT license.
3 |
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.Windows.Forms;
10 |
11 | namespace MiniBug
12 | {
13 | public class TasksDataGridViewRowComparer : System.Collections.IComparer
14 | {
15 | private static int sortOrderModifierColumn1 = 1;
16 | private static int sortOrderModifierColumn2 = 1;
17 |
18 | public TasksDataGridViewRowComparer(SortOrder sortOrder)
19 | {
20 | if (ApplicationSettings.GridTasksSort.FirstColumnSortOrder == SortOrder.Descending)
21 | {
22 | sortOrderModifierColumn1 = -1;
23 | }
24 | else if (ApplicationSettings.GridTasksSort.FirstColumnSortOrder == SortOrder.Ascending)
25 | {
26 | sortOrderModifierColumn1 = 1;
27 | }
28 |
29 | if (ApplicationSettings.GridTasksSort.SecondColumnSortOrder != null)
30 | {
31 | if (ApplicationSettings.GridTasksSort.SecondColumnSortOrder == SortOrder.Descending)
32 | {
33 | sortOrderModifierColumn2 = -1;
34 | }
35 | else if (ApplicationSettings.GridTasksSort.SecondColumnSortOrder == SortOrder.Ascending)
36 | {
37 | sortOrderModifierColumn2 = 1;
38 | }
39 | }
40 | }
41 |
42 | private int CompareValues(TaskFieldsUI fieldType, object field1, object field2)
43 | {
44 | switch (fieldType)
45 | {
46 | case TaskFieldsUI.ID:
47 | case TaskFieldsUI.Status:
48 | case TaskFieldsUI.Priority:
49 | int value1 = Convert.ToInt32(field1);
50 | int value2 = Convert.ToInt32(field2);
51 |
52 | if (value1 < value2)
53 | {
54 | return -1;
55 | }
56 | else if (value1 == value2)
57 | {
58 | return 0;
59 | }
60 | else
61 | {
62 | return 1;
63 | }
64 |
65 | case TaskFieldsUI.TargetVersion:
66 | case TaskFieldsUI.Summary:
67 | return string.Compare(field1.ToString(), field2.ToString());
68 |
69 | case TaskFieldsUI.DateCreated:
70 | case TaskFieldsUI.DateModified:
71 | DateTime dtValue1, dtValue2;
72 |
73 | if ((DateTime.TryParse(field1.ToString(), out dtValue1)) && (DateTime.TryParse(field2.ToString(), out dtValue2)))
74 | {
75 | if (dtValue1 < dtValue2)
76 | {
77 | return -1;
78 | }
79 | else if (dtValue1 == dtValue2)
80 | {
81 | return 0;
82 | }
83 | else
84 | {
85 | return 1;
86 | }
87 | }
88 |
89 | return 0;
90 |
91 | default:
92 | return 0;
93 | }
94 | }
95 |
96 | private object GetValueForField(TaskFieldsUI column, int id)
97 | {
98 | switch (column)
99 | {
100 | case TaskFieldsUI.ID:
101 | return id;
102 | case TaskFieldsUI.Priority:
103 | return Program.SoftwareProject.Tasks[id].Priority;
104 | case TaskFieldsUI.Status:
105 | return Program.SoftwareProject.Tasks[id].Status;
106 | case TaskFieldsUI.TargetVersion:
107 | return Program.SoftwareProject.Tasks[id].TargetVersion;
108 | case TaskFieldsUI.Summary:
109 | return Program.SoftwareProject.Tasks[id].Summary;
110 | case TaskFieldsUI.DateCreated:
111 | return Program.SoftwareProject.Tasks[id].DateCreated;
112 | case TaskFieldsUI.DateModified:
113 | return Program.SoftwareProject.Tasks[id].DateModified;
114 | default:
115 | return null;
116 | }
117 | }
118 |
119 | public int Compare(object x, object y)
120 | {
121 | DataGridViewRow DataGridViewRow1 = (DataGridViewRow)x;
122 | DataGridViewRow DataGridViewRow2 = (DataGridViewRow)y;
123 |
124 | int CompareResult = 0;
125 | object field1, field2;
126 |
127 | int id1 = Convert.ToInt32(DataGridViewRow1.Cells[0].Value);
128 | int id2 = Convert.ToInt32(DataGridViewRow2.Cells[0].Value);
129 |
130 | // Get the values for the first and second fields, in the first column
131 | field1 = GetValueForField(ApplicationSettings.GridTasksSort.FirstColumn, id1);
132 | field2 = GetValueForField(ApplicationSettings.GridTasksSort.FirstColumn, id2);
133 |
134 | CompareResult = CompareValues(ApplicationSettings.GridTasksSort.FirstColumn, field1, field2);
135 |
136 | // Regarding sort column 1, one of the rows is either lower or greater than the other
137 | if ((CompareResult == -1) || (CompareResult == 1))
138 | {
139 | return CompareResult * sortOrderModifierColumn1;
140 | }
141 | else
142 | {
143 | // Both rows are equal (regarding sort column 1)
144 |
145 | // If only sorting by one column, then both rows are equal
146 | if (ApplicationSettings.GridTasksSort.SecondColumn == null)
147 | {
148 | // Resort to ID to give some final order
149 | return ((id1 < id2) ? -1 : 1);
150 | }
151 |
152 | // Get the values for the first and second fields, in the second column
153 | field1 = GetValueForField(ApplicationSettings.GridTasksSort.SecondColumn.Value, id1);
154 | field2 = GetValueForField(ApplicationSettings.GridTasksSort.SecondColumn.Value, id2);
155 |
156 | CompareResult = CompareValues(ApplicationSettings.GridTasksSort.SecondColumn.Value, field1, field2);
157 |
158 | if ((CompareResult == -1) || (CompareResult == 1))
159 | {
160 | return CompareResult * sortOrderModifierColumn2;
161 | }
162 | else
163 | {
164 | // Both rows are equal: resort to ID to give some final order
165 | return ((id1 < id2) ? -1 : 1);
166 | }
167 | }
168 | }
169 | }
170 | }
171 |
--------------------------------------------------------------------------------
/MiniBug/Classes/ApplicationData.cs:
--------------------------------------------------------------------------------
1 | // Copyright(c) João Martiniano. All rights reserved.
2 | // Licensed under the MIT license.
3 |
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.Collections;
10 | using System.IO;
11 | using Newtonsoft.Json;
12 | using CsvHelper;
13 |
14 | namespace MiniBug
15 | {
16 | public enum OperationType { None = 0, New, Edit, Delete };
17 |
18 | ///
19 | /// Identify which grid to reference of performe some operation.
20 | ///
21 | public enum GridType { None = 0, All, Issues, Tasks }
22 |
23 | ///
24 | /// Result of a filesystem operation.
25 | ///
26 | public enum FileSystemOperationStatus {
27 | None = 0,
28 |
29 | /// The operation was successfull.
30 | OK = 1,
31 |
32 | /// Trying to load a project with an unsupported file format.
33 | ProjectLoadErrorUnsupportedFormat,
34 |
35 | /// Trying to load a project file from a non-existing directory.
36 | ProjectLoadErrorDirectoryNotFound,
37 |
38 | /// File not found while trying to load a project.
39 | ProjectLoadErrorFileNotFound,
40 |
41 | /// Project file path and/or file name too long.
42 | ProjectLoadErrorPathTooLong,
43 |
44 | /// Error deserializing the project file.
45 | ProjectLoadErrorDeserialization,
46 |
47 | /// General I/O error while trying to load the project file.
48 | ProjectLoadErrorIO,
49 |
50 | /// Trying to save a project file to a non-existing directory.
51 | ProjectSaveErrorDirectoryNotFound,
52 |
53 | /// Project file's path and/or file name too long.
54 | ProjectSaveErrorPathTooLong,
55 |
56 | /// Error serializing the project file.
57 | ProjectSaveErrorSerialization,
58 |
59 | /// General I/O error while trying to save the project file.
60 | ProjectSaveIOError,
61 |
62 | /// Project successfully exported.
63 | ExportOK,
64 |
65 | /// Export projet to CSV: trying to export to a non-existing directory.
66 | ExportToCsvErrorDirectoryNotFound,
67 |
68 | /// Export projet to CSV: file path and/or file name too long.
69 | ExportToCsvErrorPathTooLong,
70 |
71 | /// Export projet to CSV: error reported by the component responsible for performing the export.
72 | ExportToCsvErrorExporterComponent,
73 |
74 | /// Export projet to CSV: general I/O error.
75 | ExportToCsvIOError
76 | }
77 |
78 | public static class ApplicationData
79 | {
80 | ///
81 | /// Saves a project data to a file. The file is overwritten.
82 | ///
83 | /// An instance of the Project class.
84 | public static FileSystemOperationStatus SaveProject(in Project softwareProject)
85 | {
86 | string output = string.Empty;
87 | string filename = string.Empty;
88 |
89 | output = JsonConvert.SerializeObject(softwareProject);
90 | filename = System.IO.Path.Combine(softwareProject.Location, softwareProject.Filename);
91 |
92 | try
93 | {
94 | System.IO.File.WriteAllText(filename, output);
95 | }
96 | catch (System.IO.DirectoryNotFoundException) // The directory does not exist
97 | {
98 | return FileSystemOperationStatus.ProjectSaveErrorDirectoryNotFound;
99 | }
100 | catch (System.IO.PathTooLongException) // The path is too long
101 | {
102 | return FileSystemOperationStatus.ProjectSaveErrorPathTooLong;
103 | }
104 | catch (JsonException) // Error serializing the project
105 | {
106 | return FileSystemOperationStatus.ProjectSaveErrorSerialization;
107 | }
108 | catch // General input/output error
109 | {
110 | return FileSystemOperationStatus.ProjectSaveIOError;
111 | }
112 |
113 | return FileSystemOperationStatus.OK;
114 | }
115 |
116 | ///
117 | /// Load project data from a file.
118 | ///
119 | /// Name and location of the project file.
120 | /// An instance of the Project class.
121 | public static FileSystemOperationStatus LoadProject(string filename, out Project softwareProject)
122 | {
123 | String input = string.Empty;
124 |
125 | try
126 | {
127 | // Open the file
128 | System.IO.StreamReader r = new System.IO.StreamReader(filename);
129 |
130 | // Read the file contents
131 | input = r.ReadToEnd();
132 |
133 | r.Close();
134 |
135 | softwareProject = JsonConvert.DeserializeObject(input);
136 |
137 | // Check the version of the project file: if not supported, abort the operation
138 | if (softwareProject.Version != ApplicationSettings.ProjectFileFormatVersion)
139 | {
140 | softwareProject = null;
141 | return FileSystemOperationStatus.ProjectLoadErrorUnsupportedFormat;
142 | }
143 |
144 | // Insert the path and filename into the project
145 | softwareProject.Location = Path.GetDirectoryName(filename);
146 | softwareProject.Filename = Path.GetFileName(filename);
147 | }
148 | catch (System.IO.DirectoryNotFoundException) // The directory does not exist
149 | {
150 | softwareProject = null;
151 | return FileSystemOperationStatus.ProjectLoadErrorDirectoryNotFound;
152 | }
153 | catch (System.IO.FileNotFoundException) // The file does not exist
154 | {
155 | softwareProject = null;
156 | return FileSystemOperationStatus.ProjectLoadErrorFileNotFound;
157 | }
158 | catch (System.IO.PathTooLongException) // The path is too long
159 | {
160 | softwareProject = null;
161 | return FileSystemOperationStatus.ProjectLoadErrorPathTooLong;
162 | }
163 | catch (JsonException) // Error deserializing the file
164 | {
165 | softwareProject = null;
166 | return FileSystemOperationStatus.ProjectLoadErrorDeserialization;
167 | }
168 | catch // General input/output error
169 | {
170 | softwareProject = null;
171 | return FileSystemOperationStatus.ProjectLoadErrorIO;
172 | }
173 |
174 | return FileSystemOperationStatus.OK;
175 | }
176 | }
177 | }
178 |
--------------------------------------------------------------------------------
/MiniBug/Classes/IssuesDataGridViewRowComparer.cs:
--------------------------------------------------------------------------------
1 | // Copyright(c) João Martiniano. All rights reserved.
2 | // Licensed under the MIT license.
3 |
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.Windows.Forms;
10 |
11 | namespace MiniBug
12 | {
13 | public class IssuesDataGridViewRowComparer : System.Collections.IComparer
14 | {
15 | private static int sortOrderModifierColumn1 = 1;
16 | private static int sortOrderModifierColumn2 = 1;
17 |
18 | public IssuesDataGridViewRowComparer(SortOrder sortOrder)
19 | {
20 | if (ApplicationSettings.GridIssuesSort.FirstColumnSortOrder == SortOrder.Descending)
21 | {
22 | sortOrderModifierColumn1 = -1;
23 | }
24 | else if (ApplicationSettings.GridIssuesSort.FirstColumnSortOrder == SortOrder.Ascending)
25 | {
26 | sortOrderModifierColumn1 = 1;
27 | }
28 |
29 | if (ApplicationSettings.GridIssuesSort.SecondColumnSortOrder != null)
30 | {
31 | if (ApplicationSettings.GridIssuesSort.SecondColumnSortOrder == SortOrder.Descending)
32 | {
33 | sortOrderModifierColumn2 = -1;
34 | }
35 | else if (ApplicationSettings.GridIssuesSort.SecondColumnSortOrder == SortOrder.Ascending)
36 | {
37 | sortOrderModifierColumn2 = 1;
38 | }
39 | }
40 | }
41 |
42 | private int CompareValues(IssueFieldsUI fieldType, object field1, object field2)
43 | {
44 | switch (fieldType)
45 | {
46 | case IssueFieldsUI.ID:
47 | case IssueFieldsUI.Status:
48 | case IssueFieldsUI.Priority:
49 | int value1 = Convert.ToInt32(field1);
50 | int value2 = Convert.ToInt32(field2);
51 |
52 | if (value1 < value2)
53 | {
54 | return -1;
55 | }
56 | else if (value1 == value2)
57 | {
58 | return 0;
59 | }
60 | else
61 | {
62 | return 1;
63 | }
64 |
65 | case IssueFieldsUI.Version:
66 | case IssueFieldsUI.TargetVersion:
67 | case IssueFieldsUI.Summary:
68 | return string.Compare(field1.ToString(), field2.ToString());
69 |
70 | case IssueFieldsUI.DateCreated:
71 | case IssueFieldsUI.DateModified:
72 | DateTime dtValue1, dtValue2;
73 |
74 | if ((DateTime.TryParse(field1.ToString(), out dtValue1)) && (DateTime.TryParse(field2.ToString(), out dtValue2)))
75 | {
76 | if (dtValue1 < dtValue2)
77 | {
78 | return -1;
79 | }
80 | else if (dtValue1 == dtValue2)
81 | {
82 | return 0;
83 | }
84 | else
85 | {
86 | return 1;
87 | }
88 | }
89 |
90 | return 0;
91 |
92 | default:
93 | return 0;
94 | }
95 | }
96 |
97 | private object GetValueForField(IssueFieldsUI column, int id)
98 | {
99 | switch (column)
100 | {
101 | case IssueFieldsUI.ID:
102 | return id;
103 | case IssueFieldsUI.Priority:
104 | return Program.SoftwareProject.Issues[id].Priority;
105 | case IssueFieldsUI.Status:
106 | return Program.SoftwareProject.Issues[id].Status;
107 | case IssueFieldsUI.Version:
108 | return Program.SoftwareProject.Issues[id].Version;
109 | case IssueFieldsUI.TargetVersion:
110 | return Program.SoftwareProject.Issues[id].TargetVersion;
111 | case IssueFieldsUI.Summary:
112 | return Program.SoftwareProject.Issues[id].Summary;
113 | case IssueFieldsUI.DateCreated:
114 | return Program.SoftwareProject.Issues[id].DateCreated;
115 | case IssueFieldsUI.DateModified:
116 | return Program.SoftwareProject.Issues[id].DateModified;
117 | default:
118 | return null;
119 | }
120 | }
121 |
122 | public int Compare(object x, object y)
123 | {
124 | DataGridViewRow DataGridViewRow1 = (DataGridViewRow)x;
125 | DataGridViewRow DataGridViewRow2 = (DataGridViewRow)y;
126 |
127 | int CompareResult = 0;
128 | object field1, field2;
129 |
130 | int id1 = Convert.ToInt32(DataGridViewRow1.Cells[0].Value);
131 | int id2 = Convert.ToInt32(DataGridViewRow2.Cells[0].Value);
132 |
133 | // Get the values for the first and second fields, in the first column
134 | field1 = GetValueForField(ApplicationSettings.GridIssuesSort.FirstColumn, id1);
135 | field2 = GetValueForField(ApplicationSettings.GridIssuesSort.FirstColumn, id2);
136 |
137 | CompareResult = CompareValues(ApplicationSettings.GridIssuesSort.FirstColumn, field1, field2);
138 |
139 | // Regarding sort column 1, one of the rows is either lower or greater than the other
140 | if ((CompareResult == -1) || (CompareResult == 1))
141 | {
142 | return CompareResult * sortOrderModifierColumn1;
143 | }
144 | else
145 | {
146 | // Both rows are equal (regarding sort column 1)
147 |
148 | // If only sorting by one column, then both rows are equal
149 | if (ApplicationSettings.GridIssuesSort.SecondColumn == null)
150 | {
151 | // Resort to ID to give some final order
152 | return ((id1 < id2) ? -1 : 1);
153 | }
154 |
155 | // Get the values for the first and second fields, in the second column
156 | field1 = GetValueForField(ApplicationSettings.GridIssuesSort.SecondColumn.Value, id1);
157 | field2 = GetValueForField(ApplicationSettings.GridIssuesSort.SecondColumn.Value, id2);
158 |
159 | CompareResult = CompareValues(ApplicationSettings.GridIssuesSort.SecondColumn.Value, field1, field2);
160 |
161 | if ((CompareResult == -1) || (CompareResult == 1))
162 | {
163 | return CompareResult * sortOrderModifierColumn2;
164 | }
165 | else
166 | {
167 | // Both rows are equal: resort to ID to give some final order
168 | return ((id1 < id2) ? -1 : 1);
169 | }
170 | }
171 | }
172 | }
173 | }
174 |
--------------------------------------------------------------------------------
/MiniBug/AboutForm.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 |
122 |
123 | iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAABHNCSVQICAgIfAhkiAAAAAFzUkdCAK7O
124 | HOkAAAAEZ0FNQQAAsY8L/GEFAAAACXBIWXMAADsKAAA7CgEzSyaRAAAAGXRFWHRTb2Z0d2FyZQB3d3cu
125 | aW5rc2NhcGUub3Jnm+48GgAAAn1JREFUeF7tmzFuE2EYRF1Q0XMCTkBBQWHJ67WEKHyBdIiOlgPARbgD
126 | J6DmDvRIdEjQRCgOf6QprCeR7M6s/3zFPmna983YWsvNblZWVlYeYhzHVy1f9vv9n5bbR8rP1uGlKvWj
127 | Hd2249co81i5+wLeqFof2sGvZwUq5G/LW9W7PO3Yr7PjVXJq+aSKlwWHb3vD++dpj+fn3W73RFUvA4/2
128 | hveZux/n4/H4VHWXhwd7w/v/ybftdvtMlZeFx3rD+/fke8tz1V4OHFGtfvD+fWmPw4/D4fBC1ZeBR3rD
129 | +xPyexiG16qfwwO94f2JuW4fwpUmZFDeG96fkWX+K0CqWv3g/bnRDB8Ke8P7c6MZPhT2hvfnRjN8KOwN
130 | 78+NZvhQmEIfk0KfZvhQmEIfk0KfZvhQmEIfk0KfZvhQmEIfk0KfZvhQmEIfk0KfZvhQmEIfk0KfZvhQ
131 | mEIfk0KfZvhQmEIfk0KfZvhQmEIfk0KfZvhQmEIfk0KfZvhQmEIfk0KfZvhQmEIfk0KfZvhQmEIfk0Kf
132 | ZvhQmEIfk0KfZvhQmEIfk0KfZvhQmEIfk0KfZvhQWB321QwfCqvDvprhQ2F12FczfCisDvtqhg+FKfQx
133 | KfRphg+FKfQxKfRphg+FKfQxKfRphg+FKfQxKfRphg+FKfQxKfRphg+FKfQxKfRphg+FKfQxKfRphg+F
134 | KfQxKfRphg+F1WFfzfChsDrsqxk+FFaHfTXDh8LqsK9m+FBYHfbVDB8Kq8O+muFDYXXYVzN8KKwO+2qG
135 | T5NUfGFiaj5qhk+TVHtlZkpO4zh+0ISMYi9NTclpGIb3qr8M7UOo8NrclNy0nu9Ue2VlZeUBNpt/1Pqv
136 | vTzMmPUAAAAASUVORK5CYII=
137 |
138 |
139 |
--------------------------------------------------------------------------------
/MiniBug/FeedbackForm.cs:
--------------------------------------------------------------------------------
1 | // Copyright(c) João Martiniano. All rights reserved.
2 | // Licensed under the MIT license.
3 |
4 | using System;
5 | using System.Collections.Generic;
6 | using System.ComponentModel;
7 | using System.Data;
8 | using System.Drawing;
9 | using System.Linq;
10 | using System.Text;
11 | using System.Threading.Tasks;
12 | using System.Windows.Forms;
13 |
14 | namespace MiniBug
15 | {
16 | public partial class FeedbackForm : Form
17 | {
18 | ///
19 | /// Gets or sets the caption of the form.
20 | ///
21 | public string FormCaption { get; set; } = string.Empty;
22 |
23 | ///
24 | /// Gets or sets the feedback message title.
25 | ///
26 | public string MessageTitle { get; set; } = string.Empty;
27 |
28 | ///
29 | /// Gets or sets the feedback message.
30 | ///
31 | public string Message { get; set; } = string.Empty;
32 |
33 | ///
34 | /// Gets or sets the image displayed in the form.
35 | ///
36 | public Image FormImage { get; set; } = null;
37 |
38 | public FeedbackForm()
39 | {
40 | InitializeComponent();
41 | }
42 |
43 | private void FeedbackForm_Load(object sender, EventArgs e)
44 | {
45 | this.AcceptButton = btClose;
46 | }
47 |
48 | public void SetUserInterface()
49 | {
50 | // Suspend the layout logic for the form, while the application is initializing
51 | this.SuspendLayout();
52 |
53 | this.Text = FormCaption;
54 | lblMessageTitle.Text = MessageTitle;
55 | lblMessageTitle.AutoEllipsis = true;
56 | lblMessage.Text = Message;
57 |
58 | pictureBox1.Image = FormImage;
59 | pictureBox1.Left = (lblMessageTitle.Left / 2) - (pictureBox1.Width / 2);
60 |
61 | // Resume the layout logic
62 | this.ResumeLayout();
63 | }
64 |
65 | public void ComposeMessage(FileSystemOperationStatus MessageType)
66 | {
67 | switch (MessageType)
68 | {
69 | // Errors while opening a project
70 |
71 | case FileSystemOperationStatus.ProjectLoadErrorUnsupportedFormat:
72 | FormCaption = "Project Read Error";
73 | MessageTitle = "Error Reading Project File: Unsupported Project Format";
74 | Message = "This version of MiniBug does not support this project file format: it appears it was created using another version of the program.";
75 | Message += "\n\nSolution: use another version of this program to open the project file.";
76 | FormImage = MiniBug.Properties.Resources.FileError_64x64;
77 | break;
78 |
79 | case FileSystemOperationStatus.ProjectLoadErrorDirectoryNotFound:
80 | FormCaption = "Project Read Error";
81 | MessageTitle = "Error Reading Project File: Location Not Found";
82 | Message = "The specified location does not exist.";
83 | FormImage = MiniBug.Properties.Resources.FolderError_64x64;
84 | break;
85 |
86 | case FileSystemOperationStatus.ProjectLoadErrorFileNotFound:
87 | FormCaption = "Project Read Error";
88 | MessageTitle = "Error Reading Project File: File Not Found";
89 | Message = "The specified file was not found.";
90 | Message += "\n\nPlease choose a different project file.";
91 | FormImage = MiniBug.Properties.Resources.FileError_64x64;
92 | break;
93 |
94 | case FileSystemOperationStatus.ProjectLoadErrorPathTooLong:
95 | FormCaption = "Project Read Error";
96 | MessageTitle = "Error Reading Project File: Path Too Long";
97 | Message = "The project path, filename or both are too long.";
98 | Message += "\n\nSolution: choose a project file with a shorter path and/or shorter filename.";
99 | FormImage = MiniBug.Properties.Resources.FileError_64x64;
100 | break;
101 |
102 | case FileSystemOperationStatus.ProjectLoadErrorDeserialization:
103 | FormCaption = "Project Read Error";
104 | MessageTitle = "Error Reading Project File: Unsupported Project Format";
105 | Message = "The project file appears to be damaged or in an incorrect format.";
106 | FormImage = MiniBug.Properties.Resources.FileError_64x64;
107 | break;
108 |
109 | case FileSystemOperationStatus.ProjectLoadErrorIO:
110 | FormCaption = "Project Read Error";
111 | MessageTitle = "Error Reading Project File: I/O Error";
112 | Message = "There was a general input/output error while reading this project.";
113 | Message += "\n\nCheck the status of the drive/device where the project file is stored.";
114 | FormImage = MiniBug.Properties.Resources.CriticalError_64x64;
115 | break;
116 |
117 | // Errors while saving a project
118 |
119 | case FileSystemOperationStatus.ProjectSaveErrorDirectoryNotFound:
120 | FormCaption = "Project Save Error";
121 | MessageTitle = "Error Saving Project File: Location Not Found";
122 | Message = "The specified location does not exist.";
123 | Message += "\n\nSolution: choose a different location for the project file.";
124 | FormImage = MiniBug.Properties.Resources.FolderError_64x64;
125 | break;
126 |
127 | case FileSystemOperationStatus.ProjectSaveErrorPathTooLong:
128 | FormCaption = "Project Save Error";
129 | MessageTitle = "Error Saving Project File: Path Too Long";
130 | Message = "The project path, file name or both are too long.";
131 | Message += "\n\nSolution: choose a different location and/or a shorter filename.";
132 | FormImage = MiniBug.Properties.Resources.FileError_64x64;
133 | break;
134 |
135 | case FileSystemOperationStatus.ProjectSaveErrorSerialization:
136 | FormCaption = "Project Save Error";
137 | MessageTitle = "Error Saving Project File: Unable to Save";
138 | Message = "The project data appears to be damaged or in an incorrect format.";
139 | FormImage = MiniBug.Properties.Resources.FileError_64x64;
140 | break;
141 |
142 | case FileSystemOperationStatus.ProjectSaveIOError:
143 | FormCaption = "Project Save Error";
144 | MessageTitle = "Error Saving Project File: I/O Error";
145 | Message = "There was a general input/output error while saving this project.";
146 | Message += "\n\nSolution: choose a different drive/device to save the project file.";
147 | FormImage = MiniBug.Properties.Resources.CriticalError_64x64;
148 | break;
149 | }
150 |
151 | // Update the user interface
152 | SetUserInterface();
153 | }
154 |
155 | ///
156 | /// Close the form.
157 | ///
158 | private void btClose_Click(object sender, EventArgs e)
159 | {
160 | this.Close();
161 | }
162 | }
163 | }
164 |
--------------------------------------------------------------------------------
/MiniBug/TaskForm.cs:
--------------------------------------------------------------------------------
1 | // Copyright(c) João Martiniano. All rights reserved.
2 | // Licensed under the MIT license.
3 |
4 | using System;
5 | using System.Collections.Generic;
6 | using System.ComponentModel;
7 | using System.Data;
8 | using System.Drawing;
9 | using System.Linq;
10 | using System.Text;
11 | using System.Threading.Tasks;
12 | using System.Windows.Forms;
13 |
14 | namespace MiniBug
15 | {
16 | public partial class TaskForm : Form
17 | {
18 | ///
19 | /// The current operation.
20 | ///
21 | public MiniBug.OperationType Operation { get; private set; } = OperationType.None;
22 |
23 | ///
24 | /// The current task (being created or edited).
25 | ///
26 | public MiniBug.Task CurrentTask { get; private set; } = null;
27 |
28 | ///
29 | /// List of status options.
30 | ///
31 | private List StatusOptionsList = new List();
32 |
33 | ///
34 | /// List of priority options.
35 | ///
36 | private List PriorityList = new List();
37 |
38 | public TaskForm(OperationType operation, MiniBug.Task task = null)
39 | {
40 | InitializeComponent();
41 |
42 | Operation = operation;
43 |
44 | if (Operation == OperationType.New)
45 | {
46 | // Create a new instance of the Task class
47 | CurrentTask = new Task();
48 | }
49 | else if ((Operation == OperationType.Edit) && (task != null))
50 | {
51 | // Edit an existing task
52 | CurrentTask = task;
53 | }
54 |
55 | // Populate the status list
56 | foreach (TaskStatus stat in Enum.GetValues(typeof(TaskStatus)))
57 | {
58 | if (stat != TaskStatus.None)
59 | {
60 | StatusOptionsList.Add(new ComboBoxItem(Convert.ToInt32(stat), stat.ToDescription()));
61 | }
62 | }
63 |
64 | // Populate the priority list
65 | foreach (TaskPriority p in Enum.GetValues(typeof(TaskPriority)))
66 | {
67 | if (p != TaskPriority.None)
68 | {
69 | PriorityList.Add(new ComboBoxItem(Convert.ToInt32(p), p.ToString()));
70 | }
71 | }
72 | }
73 |
74 | private void TaskForm_Load(object sender, EventArgs e)
75 | {
76 | // Suspend the layout logic for the form, while the application is initializing
77 | this.SuspendLayout();
78 |
79 | this.Icon = MiniBug.Properties.Resources.Minibug;
80 | this.AcceptButton = btOk;
81 | this.CancelButton = btCancel;
82 | this.MinimumSize = new Size(690, 351);
83 |
84 | txtDescription.AcceptsReturn = true;
85 | txtDescription.ScrollBars = ScrollBars.Vertical;
86 |
87 | // Initialize and populate the Status combobox
88 | cboStatus.AutoCompleteMode = AutoCompleteMode.None;
89 | cboStatus.DropDownStyle = ComboBoxStyle.DropDownList;
90 | cboStatus.DataSource = StatusOptionsList;
91 | cboStatus.ValueMember = "Value";
92 | cboStatus.DisplayMember = "Text";
93 |
94 | // Initialize and populate the Priority combobox
95 | cboPriority.AutoCompleteMode = AutoCompleteMode.None;
96 | cboPriority.DropDownStyle = ComboBoxStyle.DropDownList;
97 | cboPriority.DataSource = PriorityList;
98 | cboPriority.ValueMember = "Value";
99 | cboPriority.DisplayMember = "Text";
100 |
101 | // Make initializations based on the type of operation
102 | if (Operation == OperationType.New)
103 | {
104 | this.Text = "Add New Task";
105 | lblDateCreatedTitle.Visible = false;
106 | lblDateCreated.Visible = false;
107 | lblDateModifiedTitle.Visible = false;
108 | lblDateModified.Visible = false;
109 |
110 | cboStatus.SelectedIndex = 0;
111 | cboPriority.SelectedIndex = 0;
112 |
113 | lblID.Text = Program.SoftwareProject.TaskIdCounter.ToString();
114 | }
115 | else if (Operation == OperationType.Edit)
116 | {
117 | this.Text = "Edit Task";
118 |
119 | // Populate the controls
120 | lblDateCreated.Text = CurrentTask.DateCreated.ToString();
121 | lblDateModified.Text = CurrentTask.DateModified.ToString();
122 | txtSummary.Text = CurrentTask.Summary;
123 | txtTargetVersion.Text = CurrentTask.TargetVersion;
124 | txtDescription.Text = CurrentTask.Description;
125 |
126 | cboStatus.SelectedValue = Convert.ToInt32(CurrentTask.Status);
127 | cboPriority.SelectedValue = Convert.ToInt32(CurrentTask.Priority);
128 |
129 | lblID.Text = CurrentTask.ID.ToString();
130 | }
131 |
132 | txtDescription.Font = ApplicationSettings.FormDescriptionFieldFont;
133 |
134 | // Resume the layout logic
135 | this.ResumeLayout();
136 |
137 | SetAccessibilityInformation();
138 | }
139 |
140 | ///
141 | /// Add accessibility data to form controls.
142 | ///
143 | private void SetAccessibilityInformation()
144 | {
145 | lblID.AccessibleName = "Task ID";
146 | lblID.AccessibleDescription = "Unique numerical code assigned to the task";
147 | lblDateCreated.AccessibleName = "Date Created";
148 | lblDateCreated.AccessibleDescription = "Date/time when the task was created";
149 | lblDateModified.AccessibleName = "Date Modified";
150 | lblDateModified.AccessibleDescription = "Date/time when the task was last modified";
151 | txtSummary.AccessibleDescription = "Brief summary of the task";
152 | cboStatus.AccessibleDescription = "Current status of the task";
153 | cboPriority.AccessibleDescription = "Priority of a task";
154 | txtTargetVersion.AccessibleDescription = "Version where the task must be resolved";
155 | txtDescription.AccessibleDescription = "Extended description of the task";
156 | }
157 |
158 | ///
159 | /// Close the form.
160 | ///
161 | private void btOk_Click(object sender, EventArgs e)
162 | {
163 | if (txtSummary.Text != string.Empty)
164 | {
165 | CurrentTask.Summary = txtSummary.Text;
166 | CurrentTask.Status = ((TaskStatus)((MiniBug.ComboBoxItem)cboStatus.SelectedItem).Value);
167 | CurrentTask.Priority = ((TaskPriority)((MiniBug.ComboBoxItem)cboPriority.SelectedItem).Value);
168 | CurrentTask.TargetVersion = txtTargetVersion.Text;
169 | CurrentTask.Description = txtDescription.Text;
170 |
171 | if (Operation == OperationType.New)
172 | {
173 | CurrentTask.DateCreated = DateTime.Now;
174 | }
175 |
176 | CurrentTask.DateModified = DateTime.Now;
177 |
178 | this.DialogResult = DialogResult.OK;
179 | this.Close();
180 | }
181 | }
182 |
183 | ///
184 | /// Cancel this operation and close the form.
185 | ///
186 | private void btCancel_Click(object sender, EventArgs e)
187 | {
188 | this.DialogResult = DialogResult.Cancel;
189 | this.Close();
190 | }
191 | }
192 | }
193 |
--------------------------------------------------------------------------------
/MiniBug/ExportForm.cs:
--------------------------------------------------------------------------------
1 | // Copyright(c) João Martiniano. All rights reserved.
2 | // Licensed under the MIT license.
3 |
4 | using System;
5 | using System.Collections.Generic;
6 | using System.ComponentModel;
7 | using System.Data;
8 | using System.Drawing;
9 | using System.Linq;
10 | using System.Text;
11 | using System.Threading.Tasks;
12 | using System.Windows.Forms;
13 |
14 | namespace MiniBug
15 | {
16 | public partial class ExportForm : Form
17 | {
18 | ///
19 | /// True if the project has issues.
20 | ///
21 | private bool HasIssues = false;
22 |
23 | ///
24 | /// True if the project has tasks.
25 | ///
26 | private bool HasTasks = false;
27 |
28 | ///
29 | /// Location where the files will be exported.
30 | ///
31 | private string FilesLocation = string.Empty;
32 |
33 | ///
34 | /// File name of the issues .CSV file.
35 | ///
36 | public string IssuesFilename { get; private set; } = string.Empty;
37 |
38 | ///
39 | /// File name of the tasks .CSV file.
40 | ///
41 | public string TasksFilename { get; private set; } = string.Empty;
42 |
43 | public ExportForm()
44 | {
45 | InitializeComponent();
46 |
47 | HasIssues = ((Program.SoftwareProject.Issues != null) && (Program.SoftwareProject.Issues.Count > 0)) ? true : false;
48 | HasTasks = ((Program.SoftwareProject.Tasks != null) && (Program.SoftwareProject.Tasks.Count > 0)) ? true : false;
49 |
50 | IssuesFilename = $"{Program.SoftwareProject.Name} - Issues";
51 | TasksFilename = $"{Program.SoftwareProject.Name} - Tasks";
52 | FilesLocation = Program.SoftwareProject.Location;
53 | }
54 |
55 | private void ExportForm_Load(object sender, EventArgs e)
56 | {
57 | // Suspend the layout logic for the form, while the application is initializing
58 | this.SuspendLayout();
59 |
60 | this.AcceptButton = btExport;
61 | this.CancelButton = btCancel;
62 |
63 | lblFormTitle.Width = this.ClientRectangle.Width;
64 |
65 | txtIssuesFilename.MaxLength = 251;
66 | txtTasksFilename.MaxLength = 251;
67 | txtLocation.Text = FilesLocation;
68 |
69 | if (HasIssues && HasTasks)
70 | {
71 | lblInfo.Text = "This project will be exported to two CSV files: a file containing the issues and a file containing the tasks.";
72 | txtIssuesFilename.Text = IssuesFilename;
73 | txtTasksFilename.Text = TasksFilename;
74 | }
75 | else if (HasIssues && !HasTasks)
76 | {
77 | lblInfo.Text = "This project will be exported to a .CSV file containing the issues.";
78 |
79 | // Hide controls
80 | lblTasks.Visible = false;
81 | txtTasksFilename.Visible = false;
82 | lblCsvTasks.Visible = false;
83 |
84 | // Push controls up
85 | lblLocation.Top = lblTasks.Top;
86 | txtLocation.Top = txtTasksFilename.Top;
87 | btBrowse.Top = txtLocation.Top;
88 |
89 | txtIssuesFilename.Text = IssuesFilename;
90 | }
91 | else if (!HasIssues && HasTasks)
92 | {
93 | lblInfo.Text = "This project will be exported to a .CSV file containing the tasks.";
94 |
95 | // Hide controls
96 | lblIssues.Visible = false;
97 | txtIssuesFilename.Visible = false;
98 | lblCsvIssues.Visible = false;
99 |
100 | // Push controls up
101 | lblLocation.Top = lblTasks.Top;
102 | txtLocation.Top = txtTasksFilename.Top;
103 | btBrowse.Top = txtLocation.Top;
104 |
105 | lblTasks.Top = lblIssues.Top;
106 | txtTasksFilename.Top = txtIssuesFilename.Top;
107 | lblCsvTasks.Top = lblCsvIssues.Top;
108 |
109 | txtTasksFilename.Text = TasksFilename;
110 | }
111 |
112 | SetControlsState();
113 |
114 | // Resume the layout logic
115 | this.ResumeLayout();
116 |
117 | SetAccessibilityInformation();
118 | }
119 |
120 | ///
121 | /// Add accessibility data to form controls.
122 | ///
123 | private void SetAccessibilityInformation()
124 | {
125 | txtIssuesFilename.AccessibleDescription = "The name of the file containing the project Issues";
126 | txtTasksFilename.AccessibleDescription = "The name of the file containing the project Tasks";
127 | txtLocation.AccessibleDescription = "Folder where the project file will be exported";
128 | btBrowse.AccessibleDescription = "Browse for the folder where the project will be exported";
129 | btExport.AccessibleDescription = "Start the export operation";
130 | }
131 |
132 | ///
133 | /// Set the state of controls based on certain conditions.
134 | ///
135 | private void SetControlsState()
136 | {
137 | if (HasIssues && HasTasks)
138 | {
139 | btExport.Enabled = (!string.IsNullOrWhiteSpace(txtIssuesFilename.Text) && !string.IsNullOrWhiteSpace(txtTasksFilename.Text) && !string.IsNullOrWhiteSpace(txtLocation.Text)) ? true : false;
140 | }
141 | else if (HasIssues && !HasTasks)
142 | {
143 | btExport.Enabled = (!string.IsNullOrWhiteSpace(txtIssuesFilename.Text) && !string.IsNullOrWhiteSpace(txtLocation.Text)) ? true : false;
144 | }
145 | else if (!HasIssues && HasTasks)
146 | {
147 | btExport.Enabled = (!string.IsNullOrWhiteSpace(txtTasksFilename.Text) && !string.IsNullOrWhiteSpace(txtLocation.Text)) ? true : false;
148 | }
149 |
150 | }
151 |
152 | ///
153 | /// Check if this textbox is empty.
154 | ///
155 | private void txtIssuesFilename_TextChanged(object sender, EventArgs e)
156 | {
157 | SetControlsState();
158 | }
159 |
160 | ///
161 | /// Check if this textbox is empty.
162 | ///
163 | private void txtTasksFilename_TextChanged(object sender, EventArgs e)
164 | {
165 | SetControlsState();
166 | }
167 |
168 | ///
169 | /// Browse the location where the project will be exported.
170 | ///
171 | private void btBrowse_Click(object sender, EventArgs e)
172 | {
173 | if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
174 | {
175 | txtLocation.Text = folderBrowserDialog1.SelectedPath;
176 | }
177 |
178 | SetControlsState();
179 | }
180 |
181 | ///
182 | /// Export the project.
183 | ///
184 | private void btExport_Click(object sender, EventArgs e)
185 | {
186 | IssuesFilename = System.IO.Path.Combine(txtLocation.Text, txtIssuesFilename.Text + ".csv");
187 | TasksFilename = System.IO.Path.Combine(txtLocation.Text, txtTasksFilename.Text + ".csv");
188 |
189 | this.DialogResult = DialogResult.OK;
190 | this.Close();
191 | }
192 |
193 | ///
194 | /// Cancel this operation and close the form.
195 | ///
196 | private void btCancel_Click(object sender, EventArgs e)
197 | {
198 | this.DialogResult = DialogResult.Cancel;
199 | this.Close();
200 | }
201 | }
202 | }
203 |
--------------------------------------------------------------------------------
/MiniBug/IssueForm.cs:
--------------------------------------------------------------------------------
1 | // Copyright(c) João Martiniano. All rights reserved.
2 | // Licensed under the MIT license.
3 |
4 | using System;
5 | using System.Collections.Generic;
6 | using System.ComponentModel;
7 | using System.Data;
8 | using System.Drawing;
9 | using System.Linq;
10 | using System.Text;
11 | using System.Threading.Tasks;
12 | using System.Windows.Forms;
13 |
14 | namespace MiniBug
15 | {
16 | public partial class IssueForm : Form
17 | {
18 | ///
19 | /// The current operation.
20 | ///
21 | public MiniBug.OperationType Operation { get; private set; } = OperationType.None;
22 |
23 | ///
24 | /// The current issue (being created or edited).
25 | ///
26 | public MiniBug.Issue CurrentIssue { get; private set; } = null;
27 |
28 | ///
29 | /// List of status options.
30 | ///
31 | private List StatusOptionsList = new List();
32 |
33 | ///
34 | /// List of priority options.
35 | ///
36 | private List PriorityList = new List();
37 |
38 | public IssueForm(OperationType operation, MiniBug.Issue issue = null)
39 | {
40 | InitializeComponent();
41 |
42 | Operation = operation;
43 |
44 | if (Operation == OperationType.New)
45 | {
46 | // Create a new instance of the Issue class
47 | CurrentIssue = new Issue();
48 | }
49 | else if ((Operation == OperationType.Edit) && (issue != null))
50 | {
51 | // Edit an existing issue
52 | CurrentIssue = issue;
53 | }
54 |
55 | // Populate the status list
56 | foreach (IssueStatus stat in Enum.GetValues(typeof(IssueStatus)))
57 | {
58 | if (stat != IssueStatus.None)
59 | {
60 | StatusOptionsList.Add(new ComboBoxItem(Convert.ToInt32(stat), stat.ToDescription()));
61 | }
62 | }
63 |
64 | // Populate the priority list
65 | foreach (IssuePriority p in Enum.GetValues(typeof(IssuePriority)))
66 | {
67 | if (p != IssuePriority.None)
68 | {
69 | PriorityList.Add(new ComboBoxItem(Convert.ToInt32(p), p.ToString()));
70 | }
71 | }
72 | }
73 |
74 | private void IssueForm_Load(object sender, EventArgs e)
75 | {
76 | // Suspend the layout logic for the form, while the application is initializing
77 | this.SuspendLayout();
78 |
79 | this.Icon = MiniBug.Properties.Resources.Minibug;
80 | this.AcceptButton = btOk;
81 | this.CancelButton = btCancel;
82 | this.MinimumSize = new Size(685, 351);
83 |
84 | txtDescription.AcceptsReturn = true;
85 | txtDescription.ScrollBars = ScrollBars.Vertical;
86 |
87 | // Initialize and populate the Status combobox
88 | cboStatus.AutoCompleteMode = AutoCompleteMode.None;
89 | cboStatus.DropDownStyle = ComboBoxStyle.DropDownList;
90 | cboStatus.DataSource = StatusOptionsList;
91 | cboStatus.ValueMember = "Value";
92 | cboStatus.DisplayMember = "Text";
93 |
94 | // Initialize and populate the Priority combobox
95 | cboPriority.AutoCompleteMode = AutoCompleteMode.None;
96 | cboPriority.DropDownStyle = ComboBoxStyle.DropDownList;
97 | cboPriority.DataSource = PriorityList;
98 | cboPriority.ValueMember = "Value";
99 | cboPriority.DisplayMember = "Text";
100 |
101 | // Make initializations based on the type of operation
102 | if (Operation == OperationType.New)
103 | {
104 | this.Text = "Add New Issue";
105 | lblDateCreatedTitle.Visible = false;
106 | lblDateCreated.Visible = false;
107 | lblDateModifiedTitle.Visible = false;
108 | lblDateModified.Visible = false;
109 |
110 | cboStatus.SelectedIndex = 0;
111 | cboPriority.SelectedIndex = 0;
112 |
113 | lblID.Text = Program.SoftwareProject.IssueIdCounter.ToString();
114 | }
115 | else if (Operation == OperationType.Edit)
116 | {
117 | this.Text = "Edit Issue";
118 |
119 | // Populate the controls
120 | lblDateCreated.Text = CurrentIssue.DateCreated.ToString();
121 | lblDateModified.Text = CurrentIssue.DateModified.ToString();
122 | txtSummary.Text = CurrentIssue.Summary;
123 | txtVersion.Text = CurrentIssue.Version;
124 | txtTargetVersion.Text = CurrentIssue.TargetVersion;
125 | txtDescription.Text = CurrentIssue.Description;
126 |
127 | cboStatus.SelectedValue = Convert.ToInt32(CurrentIssue.Status);
128 | cboPriority.SelectedValue = Convert.ToInt32(CurrentIssue.Priority);
129 |
130 | lblID.Text = CurrentIssue.ID.ToString();
131 | }
132 |
133 | txtDescription.Font = ApplicationSettings.FormDescriptionFieldFont;
134 |
135 | // Resume the layout logic
136 | this.ResumeLayout();
137 |
138 | SetAccessibilityInformation();
139 | }
140 |
141 | ///
142 | /// Add accessibility data to form controls.
143 | ///
144 | private void SetAccessibilityInformation()
145 | {
146 | lblID.AccessibleName = "Issue ID";
147 | lblID.AccessibleDescription = "Unique numerical code assigned to the issue";
148 | lblDateCreated.AccessibleName = "Date Created";
149 | lblDateCreated.AccessibleDescription = "Date/time when the issue was created";
150 | lblDateModified.AccessibleName = "Date Modified";
151 | lblDateModified.AccessibleDescription = "Date/time when the issue was last modified";
152 | txtSummary.AccessibleDescription = "Brief summary of the issue";
153 | cboStatus.AccessibleDescription = "Current status of the issue";
154 | cboPriority.AccessibleDescription = "Priority of an issue";
155 | txtVersion.AccessibleDescription = "Version where the issue was detected";
156 | txtTargetVersion.AccessibleDescription = "Version where the issue must be resolved";
157 | txtDescription.AccessibleDescription = "Extended description of the issue";
158 | }
159 |
160 | ///
161 | /// Close the form.
162 | ///
163 | private void btOk_Click(object sender, EventArgs e)
164 | {
165 | if (txtSummary.Text != string.Empty)
166 | {
167 | CurrentIssue.Summary = txtSummary.Text;
168 | CurrentIssue.Status = ((IssueStatus)((MiniBug.ComboBoxItem)cboStatus.SelectedItem).Value);
169 | CurrentIssue.Priority = ((IssuePriority)((MiniBug.ComboBoxItem)cboPriority.SelectedItem).Value);
170 | CurrentIssue.Version = txtVersion.Text;
171 | CurrentIssue.TargetVersion = txtTargetVersion.Text;
172 | CurrentIssue.Description = txtDescription.Text;
173 |
174 | if (Operation == OperationType.New)
175 | {
176 | CurrentIssue.DateCreated = DateTime.Now;
177 | }
178 |
179 | CurrentIssue.DateModified = DateTime.Now;
180 |
181 | this.DialogResult = DialogResult.OK;
182 | this.Close();
183 | }
184 | }
185 |
186 | ///
187 | /// Cancel this operation and close the form.
188 | ///
189 | private void btCancel_Click(object sender, EventArgs e)
190 | {
191 | this.DialogResult = DialogResult.Cancel;
192 | this.Close();
193 | }
194 | }
195 | }
196 |
--------------------------------------------------------------------------------
/MiniBug/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace MiniBug.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.9.0.0")]
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17 |
18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19 |
20 | public static Settings Default {
21 | get {
22 | return defaultInstance;
23 | }
24 | }
25 |
26 | [global::System.Configuration.UserScopedSettingAttribute()]
27 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
28 | [global::System.Configuration.DefaultSettingValueAttribute("True")]
29 | public bool GridShowBorders {
30 | get {
31 | return ((bool)(this["GridShowBorders"]));
32 | }
33 | set {
34 | this["GridShowBorders"] = value;
35 | }
36 | }
37 |
38 | [global::System.Configuration.UserScopedSettingAttribute()]
39 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
40 | [global::System.Configuration.DefaultSettingValueAttribute("197, 197, 197")]
41 | public global::System.Drawing.Color GridBorderColor {
42 | get {
43 | return ((global::System.Drawing.Color)(this["GridBorderColor"]));
44 | }
45 | set {
46 | this["GridBorderColor"] = value;
47 | }
48 | }
49 |
50 | [global::System.Configuration.UserScopedSettingAttribute()]
51 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
52 | [global::System.Configuration.DefaultSettingValueAttribute("172, 212, 253")]
53 | public global::System.Drawing.Color GridSelectionBackColor {
54 | get {
55 | return ((global::System.Drawing.Color)(this["GridSelectionBackColor"]));
56 | }
57 | set {
58 | this["GridSelectionBackColor"] = value;
59 | }
60 | }
61 |
62 | [global::System.Configuration.UserScopedSettingAttribute()]
63 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
64 | [global::System.Configuration.DefaultSettingValueAttribute("Black")]
65 | public global::System.Drawing.Color GridSelectionForeColor {
66 | get {
67 | return ((global::System.Drawing.Color)(this["GridSelectionForeColor"]));
68 | }
69 | set {
70 | this["GridSelectionForeColor"] = value;
71 | }
72 | }
73 |
74 | [global::System.Configuration.UserScopedSettingAttribute()]
75 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
76 | [global::System.Configuration.DefaultSettingValueAttribute("Segoe UI, 8.25pt")]
77 | public global::System.Drawing.Font GridFont {
78 | get {
79 | return ((global::System.Drawing.Font)(this["GridFont"]));
80 | }
81 | set {
82 | this["GridFont"] = value;
83 | }
84 | }
85 |
86 | [global::System.Configuration.UserScopedSettingAttribute()]
87 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
88 | public global::System.Collections.Specialized.StringCollection RecentProjectsNames {
89 | get {
90 | return ((global::System.Collections.Specialized.StringCollection)(this["RecentProjectsNames"]));
91 | }
92 | set {
93 | this["RecentProjectsNames"] = value;
94 | }
95 | }
96 |
97 | [global::System.Configuration.UserScopedSettingAttribute()]
98 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
99 | public global::System.Collections.Specialized.StringCollection RecentProjectsPaths {
100 | get {
101 | return ((global::System.Collections.Specialized.StringCollection)(this["RecentProjectsPaths"]));
102 | }
103 | set {
104 | this["RecentProjectsPaths"] = value;
105 | }
106 | }
107 |
108 | [global::System.Configuration.UserScopedSettingAttribute()]
109 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
110 | [global::System.Configuration.DefaultSettingValueAttribute("False")]
111 | public bool GridAlternatingRowColor {
112 | get {
113 | return ((bool)(this["GridAlternatingRowColor"]));
114 | }
115 | set {
116 | this["GridAlternatingRowColor"] = value;
117 | }
118 | }
119 |
120 | [global::System.Configuration.UserScopedSettingAttribute()]
121 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
122 | [global::System.Configuration.DefaultSettingValueAttribute("White")]
123 | public global::System.Drawing.Color GridRowBackColor {
124 | get {
125 | return ((global::System.Drawing.Color)(this["GridRowBackColor"]));
126 | }
127 | set {
128 | this["GridRowBackColor"] = value;
129 | }
130 | }
131 |
132 | [global::System.Configuration.UserScopedSettingAttribute()]
133 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
134 | [global::System.Configuration.DefaultSettingValueAttribute("White")]
135 | public global::System.Drawing.Color GridAlternateRowBackColor {
136 | get {
137 | return ((global::System.Drawing.Color)(this["GridAlternateRowBackColor"]));
138 | }
139 | set {
140 | this["GridAlternateRowBackColor"] = value;
141 | }
142 | }
143 |
144 | [global::System.Configuration.UserScopedSettingAttribute()]
145 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
146 | public int[] GridIssuesSort {
147 | get {
148 | return ((int[])(this["GridIssuesSort"]));
149 | }
150 | set {
151 | this["GridIssuesSort"] = value;
152 | }
153 | }
154 |
155 | [global::System.Configuration.UserScopedSettingAttribute()]
156 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
157 | public global::System.Collections.Specialized.StringCollection GridIssuesColumnsSettings {
158 | get {
159 | return ((global::System.Collections.Specialized.StringCollection)(this["GridIssuesColumnsSettings"]));
160 | }
161 | set {
162 | this["GridIssuesColumnsSettings"] = value;
163 | }
164 | }
165 |
166 | [global::System.Configuration.UserScopedSettingAttribute()]
167 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
168 | public int[] GridTasksSort {
169 | get {
170 | return ((int[])(this["GridTasksSort"]));
171 | }
172 | set {
173 | this["GridTasksSort"] = value;
174 | }
175 | }
176 |
177 | [global::System.Configuration.UserScopedSettingAttribute()]
178 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
179 | public global::System.Collections.Specialized.StringCollection GridTasksColumnsSettings {
180 | get {
181 | return ((global::System.Collections.Specialized.StringCollection)(this["GridTasksColumnsSettings"]));
182 | }
183 | set {
184 | this["GridTasksColumnsSettings"] = value;
185 | }
186 | }
187 | }
188 | }
189 |
--------------------------------------------------------------------------------
/MiniBug/Classes/Project.cs:
--------------------------------------------------------------------------------
1 | // Copyright(c) João Martiniano. All rights reserved.
2 | // Licensed under the MIT license.
3 |
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.IO;
10 | using Newtonsoft.Json;
11 | using CsvHelper;
12 |
13 | namespace MiniBug
14 | {
15 | ///
16 | /// Stores the issues and tasks of a software project.
17 | ///
18 | [Serializable]
19 | public class Project
20 | {
21 | ///
22 | /// Gets the file format version of the project file.
23 | ///
24 | [JsonProperty]
25 | public string Version { get; private set; } = string.Empty;
26 |
27 | ///
28 | /// Gets the current value of issue ID counter: the next issue created will have this value. This property is incremented automatically.
29 | ///
30 | [JsonProperty]
31 | public int IssueIdCounter { get; private set; } = 0;
32 |
33 | ///
34 | /// Gets the current value of task ID counter: the next task created will have this value. This property is incremented automatically.
35 | ///
36 | [JsonProperty]
37 | public int TaskIdCounter { get; private set; } = 0;
38 |
39 | ///
40 | /// Gets or sets the project name.
41 | ///
42 | public string Name { get; set; } = string.Empty;
43 |
44 | ///
45 | /// Gets or sets the name of the project file.
46 | ///
47 | [JsonIgnore]
48 | public string Filename { get; set; } = string.Empty;
49 |
50 | ///
51 | /// Gets or sets the location of the project file.
52 | ///
53 | [JsonIgnore]
54 | public string Location { get; set; } = string.Empty;
55 |
56 | ///
57 | /// Gets or sets the project issues.
58 | ///
59 | public Dictionary Issues { get; set; } = new Dictionary();
60 |
61 | ///
62 | /// Gets or sets the project tasks.
63 | ///
64 | public Dictionary Tasks { get; set; } = new Dictionary();
65 |
66 | ///
67 | /// Information about the result of the last import operation that was executed.
68 | ///
69 | public ImportExportResult ImportResult { get; set; } = null;
70 |
71 | ///
72 | /// Information about the result of the last export operation that was executed.
73 | ///
74 | public ImportExportResult ExportResult { get; set; } = null;
75 |
76 | ///
77 | /// Creates a new project.
78 | ///
79 | public Project()
80 | {
81 | Version = ApplicationSettings.ProjectFileFormatVersion;
82 | IssueIdCounter = 1;
83 | TaskIdCounter = 1;
84 | }
85 |
86 | ///
87 | /// Creates a new project.
88 | ///
89 | /// The project name.
90 | public Project(string name)
91 | {
92 | Version = ApplicationSettings.ProjectFileFormatVersion;
93 | Name = name;
94 | IssueIdCounter = 1;
95 | TaskIdCounter = 1;
96 | }
97 |
98 | ///
99 | /// Add a new issue.
100 | ///
101 | /// An instance of the Issue class to add.
102 | /// The id of the added issue.
103 | public int AddIssue(Issue newIssue)
104 | {
105 | newIssue.ID = IssueIdCounter;
106 | Issues.Add(IssueIdCounter, newIssue);
107 | IssueIdCounter++;
108 |
109 | return newIssue.ID;
110 | }
111 |
112 | ///
113 | /// Add a new task.
114 | ///
115 | /// An instance of the Task class to add.
116 | /// The id of the added task.
117 | public int AddTask(Task newTask)
118 | {
119 | newTask.ID = TaskIdCounter;
120 | Tasks.Add(TaskIdCounter, newTask);
121 | TaskIdCounter++;
122 |
123 | return newTask.ID;
124 | }
125 |
126 | ///
127 | /// Export the issues and tasks of a project to a file.
128 | ///
129 | public void Export(string fileNameIssues, string fileNameTasks)
130 | {
131 | ExportResult = new ImportExportResult(ImportExportOperation.Export);
132 |
133 | // Export the issues
134 | if ((Issues != null) && (Issues.Count > 0))
135 | {
136 | ExportResult.Issues.Result = ExportIssues(fileNameIssues);
137 | ExportResult.Issues.FileName = System.IO.Path.GetFileName(fileNameIssues);
138 | ExportResult.Issues.Path = System.IO.Path.GetDirectoryName(fileNameIssues);
139 | }
140 |
141 | // Export the tasks
142 | if ((Tasks != null) && (Tasks.Count > 0))
143 | {
144 | ExportResult.Tasks.Result = ExportTasks(fileNameTasks);
145 | ExportResult.Tasks.FileName = System.IO.Path.GetFileName(fileNameTasks);
146 | ExportResult.Tasks.Path = System.IO.Path.GetDirectoryName(fileNameTasks);
147 | }
148 | }
149 |
150 | ///
151 | /// Export the project issues.
152 | ///
153 | ///
154 | ///
155 | private FileSystemOperationStatus ExportIssues(string fileName)
156 | {
157 | try
158 | {
159 | using (var writer = new StreamWriter(fileName, false, System.Text.Encoding.UTF8))
160 | {
161 | using (var csv = new CsvWriter(writer))
162 | {
163 | csv.WriteRecords(Issues.Values);
164 | }
165 | }
166 | }
167 | catch (System.IO.DirectoryNotFoundException) // The directory does not exist
168 | {
169 | return FileSystemOperationStatus.ExportToCsvErrorDirectoryNotFound;
170 | }
171 | catch (System.IO.PathTooLongException) // The path is too long
172 | {
173 | return FileSystemOperationStatus.ExportToCsvErrorPathTooLong;
174 | }
175 | catch (CsvHelperException) // Error reported by CsvHelper
176 | {
177 | return FileSystemOperationStatus.ExportToCsvErrorExporterComponent;
178 | }
179 | catch // General input/output error
180 | {
181 | return FileSystemOperationStatus.ExportToCsvIOError;
182 | }
183 |
184 | return FileSystemOperationStatus.ExportOK;
185 | }
186 |
187 | ///
188 | /// Export the project tasks.
189 | ///
190 | ///
191 | ///
192 | ///
193 | private FileSystemOperationStatus ExportTasks(string fileName)
194 | {
195 | try
196 | {
197 | using (var writer = new StreamWriter(fileName, false, System.Text.Encoding.UTF8))
198 | {
199 | using (var csv = new CsvWriter(writer))
200 | {
201 | csv.WriteRecords(Tasks.Values);
202 | }
203 | }
204 | }
205 | catch (System.IO.DirectoryNotFoundException) // The directory does not exist
206 | {
207 | return FileSystemOperationStatus.ExportToCsvErrorDirectoryNotFound;
208 | }
209 | catch (System.IO.PathTooLongException) // The path is too long
210 | {
211 | return FileSystemOperationStatus.ExportToCsvErrorPathTooLong;
212 | }
213 | catch (CsvHelperException) // Error reported by CsvHelper
214 | {
215 | return FileSystemOperationStatus.ExportToCsvErrorExporterComponent;
216 | }
217 | catch // General input/output error
218 | {
219 | return FileSystemOperationStatus.ExportToCsvIOError;
220 | }
221 |
222 | return FileSystemOperationStatus.ExportOK;
223 | }
224 | }
225 | }
226 |
--------------------------------------------------------------------------------
/MiniBug/ConfigureViewForm.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace MiniBug
2 | {
3 | partial class ConfigureViewForm
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | this.btOK = new System.Windows.Forms.Button();
32 | this.btCancel = new System.Windows.Forms.Button();
33 | this.TabControl = new System.Windows.Forms.TabControl();
34 | this.tabPage1 = new System.Windows.Forms.TabPage();
35 | this.GridIssues = new System.Windows.Forms.DataGridView();
36 | this.tabPage2 = new System.Windows.Forms.TabPage();
37 | this.GridTasks = new System.Windows.Forms.DataGridView();
38 | this.label1 = new System.Windows.Forms.Label();
39 | this.TabControl.SuspendLayout();
40 | this.tabPage1.SuspendLayout();
41 | ((System.ComponentModel.ISupportInitialize)(this.GridIssues)).BeginInit();
42 | this.tabPage2.SuspendLayout();
43 | ((System.ComponentModel.ISupportInitialize)(this.GridTasks)).BeginInit();
44 | this.SuspendLayout();
45 | //
46 | // btOK
47 | //
48 | this.btOK.Location = new System.Drawing.Point(592, 286);
49 | this.btOK.Name = "btOK";
50 | this.btOK.Size = new System.Drawing.Size(75, 23);
51 | this.btOK.TabIndex = 2;
52 | this.btOK.Text = "OK";
53 | this.btOK.UseVisualStyleBackColor = true;
54 | this.btOK.Click += new System.EventHandler(this.btOK_Click);
55 | //
56 | // btCancel
57 | //
58 | this.btCancel.Location = new System.Drawing.Point(673, 286);
59 | this.btCancel.Name = "btCancel";
60 | this.btCancel.Size = new System.Drawing.Size(75, 23);
61 | this.btCancel.TabIndex = 3;
62 | this.btCancel.Text = "Cancel";
63 | this.btCancel.UseVisualStyleBackColor = true;
64 | this.btCancel.Click += new System.EventHandler(this.btCancel_Click);
65 | //
66 | // TabControl
67 | //
68 | this.TabControl.Controls.Add(this.tabPage1);
69 | this.TabControl.Controls.Add(this.tabPage2);
70 | this.TabControl.Location = new System.Drawing.Point(12, 44);
71 | this.TabControl.Name = "TabControl";
72 | this.TabControl.SelectedIndex = 0;
73 | this.TabControl.Size = new System.Drawing.Size(736, 236);
74 | this.TabControl.TabIndex = 1;
75 | //
76 | // tabPage1
77 | //
78 | this.tabPage1.Controls.Add(this.GridIssues);
79 | this.tabPage1.Location = new System.Drawing.Point(4, 22);
80 | this.tabPage1.Name = "tabPage1";
81 | this.tabPage1.Padding = new System.Windows.Forms.Padding(3);
82 | this.tabPage1.Size = new System.Drawing.Size(728, 210);
83 | this.tabPage1.TabIndex = 0;
84 | this.tabPage1.Text = "Issues";
85 | this.tabPage1.UseVisualStyleBackColor = true;
86 | //
87 | // GridIssues
88 | //
89 | this.GridIssues.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
90 | this.GridIssues.Dock = System.Windows.Forms.DockStyle.Fill;
91 | this.GridIssues.Location = new System.Drawing.Point(3, 3);
92 | this.GridIssues.Name = "GridIssues";
93 | this.GridIssues.Size = new System.Drawing.Size(722, 204);
94 | this.GridIssues.TabIndex = 0;
95 | this.GridIssues.CellContentClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.GridIssues_CellContentClick);
96 | this.GridIssues.CellPainting += new System.Windows.Forms.DataGridViewCellPaintingEventHandler(this.GridIssues_CellPainting);
97 | //
98 | // tabPage2
99 | //
100 | this.tabPage2.Controls.Add(this.GridTasks);
101 | this.tabPage2.Location = new System.Drawing.Point(4, 22);
102 | this.tabPage2.Name = "tabPage2";
103 | this.tabPage2.Padding = new System.Windows.Forms.Padding(3);
104 | this.tabPage2.Size = new System.Drawing.Size(728, 210);
105 | this.tabPage2.TabIndex = 1;
106 | this.tabPage2.Text = "Tasks";
107 | this.tabPage2.UseVisualStyleBackColor = true;
108 | //
109 | // GridTasks
110 | //
111 | this.GridTasks.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
112 | this.GridTasks.Dock = System.Windows.Forms.DockStyle.Fill;
113 | this.GridTasks.Location = new System.Drawing.Point(3, 3);
114 | this.GridTasks.Name = "GridTasks";
115 | this.GridTasks.Size = new System.Drawing.Size(722, 204);
116 | this.GridTasks.TabIndex = 0;
117 | this.GridTasks.CellContentClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.GridTasks_CellContentClick);
118 | this.GridTasks.CellPainting += new System.Windows.Forms.DataGridViewCellPaintingEventHandler(this.GridTasks_CellPainting);
119 | //
120 | // label1
121 | //
122 | this.label1.AutoSize = true;
123 | this.label1.Location = new System.Drawing.Point(13, 17);
124 | this.label1.Name = "label1";
125 | this.label1.Size = new System.Drawing.Size(510, 13);
126 | this.label1.TabIndex = 0;
127 | this.label1.Text = "Select which columns to show and which columns to use for sorting in the Issues a" +
128 | "nd Tasks grids:";
129 | //
130 | // ConfigureViewForm
131 | //
132 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
133 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
134 | this.ClientSize = new System.Drawing.Size(760, 321);
135 | this.Controls.Add(this.label1);
136 | this.Controls.Add(this.TabControl);
137 | this.Controls.Add(this.btCancel);
138 | this.Controls.Add(this.btOK);
139 | this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
140 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
141 | this.MaximizeBox = false;
142 | this.MinimizeBox = false;
143 | this.Name = "ConfigureViewForm";
144 | this.ShowIcon = false;
145 | this.ShowInTaskbar = false;
146 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
147 | this.Text = "Configure Columns";
148 | this.Load += new System.EventHandler(this.ConfigureViewForm_Load);
149 | this.TabControl.ResumeLayout(false);
150 | this.tabPage1.ResumeLayout(false);
151 | ((System.ComponentModel.ISupportInitialize)(this.GridIssues)).EndInit();
152 | this.tabPage2.ResumeLayout(false);
153 | ((System.ComponentModel.ISupportInitialize)(this.GridTasks)).EndInit();
154 | this.ResumeLayout(false);
155 | this.PerformLayout();
156 |
157 | }
158 |
159 | #endregion
160 | private System.Windows.Forms.Button btOK;
161 | private System.Windows.Forms.Button btCancel;
162 | private System.Windows.Forms.TabControl TabControl;
163 | private System.Windows.Forms.TabPage tabPage1;
164 | private System.Windows.Forms.TabPage tabPage2;
165 | private System.Windows.Forms.DataGridView GridIssues;
166 | private System.Windows.Forms.Label label1;
167 | private System.Windows.Forms.DataGridView GridTasks;
168 | }
169 | }
--------------------------------------------------------------------------------