Easy Project Organisation Software "OrgaNicer"
by kalauer in Circuits > Software
381 Views, 4 Favorites, 0 Comments
Easy Project Organisation Software "OrgaNicer"
I do like to create new stuff or bringing my ideas to live, and since you are browsing "instructables", I assume you are similar.
The best feeling is to see your creation in reality or when your ideas are assembled and everything comes out as expected.
Once the project is finished and you're the proudest person alive, you have to take care of the other "necessary" stuff like cleaning the workshop or store the created files / drawings / etc in the most intelligent way.
That is my lease favorite parts of every project.
Due to the fact that I can't skip the cleaning part, I tried to figure out a way to speed up the file organisation.
In this instructable I will not only show you the way I created a software to solve this step, but I also want to share the program itself in case you are not that into software programming.
Now feel free to use my program to get over any software chaos:-)
Unfortunately I have no Idea how to share the "exe" here, since it has around 140MB.
Let me know in the comments if you have any Idea.
The project template export is attached to step 2.
Supplies
For this project you only need Software and a capable PC.
I am using "Visual Studio 2019 Comunity edition" since it is free to use and one of the most powerfull development tool (for me).
Install of Visual Studio + Feature for C#
First of all yo need to install "Visual Studio 2019" with the necessary Features. In my case I installed the Windows C# Forms Application and some other Tools as shown in the Screenshot.
Create a New Project
Now it was time to add a new Project, in my case I named it "OrgaNicer". Select a Project Folder and continue to the next Step
As an Addition, I exported the Software as an VisualStudio 2019 template that you can easily copy the OrgaNicer_template.zip.txt into the Folder "...User\Documents\Visual Studio 2019\Templates\ProjectTemplates" and rename it to ".zip".
Downloads
Design the GUI
Now the Basic Forms application is created automatically. Next is to add some Functions to the GUI (Graphical User Interface) like Buttons, Views, Grids, Textboxes and so on.
Once you are happy with the look and the functions you added to the Form, you need to set up the functionalities behind each box or button.
I started by adding Tabs to the Form to organise the functions. Three Tabs are necessery, "Browse", "Create" and "Settings". To make the tabControl1 fill the Form1, you have to set the "Dock" to "Fill". Now the tabControl1 will resize if you increase or decrease the size of the Form1 window.
To add a function to a button, just double-click the button and the function will be automatically added in the *.cs file. You just have to add the lines of code you want to run after the user clicks the button, that's it.
Since there are so many great turtorials out there, I am just going to explain the majour functionalities I used for the Program.
Creating / Moving / Copying Files and Folders
The most used functions in this program are file or directory based functions. Creating folders, copying files or moving files to different directories are the "Must have" functions of my project organising tool.
Creating the Subdirectories:
if (Directory.Exists(RootPath + @"\" + textBox4.Text)) //This checks if the Directory already exists { MessageBox.Show("Folder / Project already exists.\n\rPlease enter another Name!"); } else { Directory.CreateDirectory(RootPath + @"\" + textBox4.Text); //This creates the Directory foreach (TreeNode treeNode in treeView1.Nodes[0].Nodes) //This goes through the List of Subdirectories { Directory.CreateDirectory(RootPath + @"\" + textBox4.Text + @"\" + treeNode.Text); //And adds them also } }
Directory.Exists(Path) returns "true" in case the directory is already there. In this example, the project folder will only be created in case it doesn't yet exist.
Directory.CreateDirectory(Path with target folder name) creates the Folder.
In the example, a Folder in directory "RootPath" with the name written in textBox4 is created as "Project Directory" and afterwards the subdirectories are created as listed as Nodes in "treeView1".
Copying the "title.png" Image
File.Delete(RootPath + @"\" + textBox4.Text + @"\title.png"); //This deletes the file File.Copy(openFileDialog1.FileName, RootPath + @"\" + textBox4.Text + @"\title.png",true); //This copies the File
File.Delete(Path) deletes the file if it exists. You could use "if (File.Exists(Path))" to check if the file is there, but it is not necessary.
File.Copy(SourcePath,TargetPath,Overwrite) copies the File to the Target Directory. Overwrite = "true" overwrites possible existing file.
Moving Files to the Project Subdirectories
if(Directory.Exists(ProjectPath + @"\" + treeNode.Text)) //This checks if the Directory already exists { File.Move(item, ProjectPath + @"\" + treeNode.Text + @"\" + item.Substring(item.LastIndexOf(@"\") + 1),true); } else { Directory.CreateDirectory(ProjectPath + @"\" + treeNode.Text); File.Move(item, ProjectPath + @"\" + treeNode.Text + @"\" + item.Substring(item.LastIndexOf(@"\") + 1),true); //This moves the File to the target Directory }
File.Move(SourcePath,TargetPath,Overwrite) this works exactly as the copy function, but it moves the file instead of creating a copy it.
XML Handling
For every Project, a XML-File is created which contains all Project information like Title, Keywords and so on. Also the Settings are stored locally in a "Settings.xml"-File.
In this Step I try to explain how to:
Create a XML File:
XmlDocument xmldoc = new XmlDocument(); //This creates a temporary object XmlNode rootNode = xmldoc.CreateElement("Project"); //This creates the rootNode xmldoc.AppendChild(rootNode); //This appends the rootNode into the file XmlNode idnode = xmldoc.CreateElement("Project_id"); //This creates further Nodes XmlNode nameNode = xmldoc.CreateElement("Project_name"); XmlNode keywordsNode = xmldoc.CreateElement("Project_keywords"); XmlNode imageNode = xmldoc.CreateElement("Project_image"); XmlNode descNode = xmldoc.CreateElement("Project_desc"); idnode.InnerText = "1"; //This assignes a value to the Node nameNode.InnerText = textBox4.Text; keywordsNode.InnerText = richTextBox4.Text; imageNode.InnerText = ""; descNode.InnerText = richTextBox5.Text; rootNode.AppendChild(idnode); //This assigns the Node to the rootNode rootNode.AppendChild(nameNode); rootNode.AppendChild(keywordsNode); rootNode.AppendChild(imageNode); rootNode.AppendChild(descNode); xmldoc.Save(RootPath + @"\" + textBox4.Text + @"\info.xml"); //This saves the resulting XML Document
First you have to create the temporary document, object or structure, in this case "xmldoc".Now that structure needs to have a "Root" Node, in this case I called it "Project" and added it to the Structure by using xmldoc.AppendChild(Name of "Root" Node).
Then I created further Nodes with the function XmlNode idnode = xmldoc.CreateElement(Name of "Child" Node); and assigned an InnerText which equals the Value of the Node by using idnode.InnerText = "Value";.
To set up the correct XML structure we have to append the ChildNode to the RootNode by using rootNode.AppendChild(idnode);.
The resulting structure is:
<Project>
<Project_id>1</Project_id>
</Project>
Last is to save the resulting xml file by xmldoc.save(path to file).
Read a XML File:
XmlDocument xmldoc = new XmlDocument(); //Create Structure XmlNodeList xmlnode; //Create Node List int i; FileStream fs = new FileStream(ProjectPath + @"\info.xml", FileMode.Open, FileAccess.Read); //Open File as File Stream xmldoc.Load(fs); //Load Filestream as XML file xmlnode = xmldoc.GetElementsByTagName("Project"); //Get Root Node for (i = 0; i <= xmlnode.Count - 1; i++) //For every "Project" in XML file, not really necessary in our use { xmlnode[i].ChildNodes.Item(0).InnerText.Trim(); // Get Child Node "0" aka Project_id richTextBox1.Text = xmlnode[i].ChildNodes.Item(4).InnerText.Trim(); //Item "4" aka Description if (File.Exists(ProjectPath + @"\" + xmlnode[i].ChildNodes.Item(3).InnerText.Trim())) { //Adding Picture, we will have a look later } else { pictureBox1.Image = null; } richTextBox2.Text = xmlnode[i].ChildNodes.Item(2).InnerText.Trim(); } fs.Close();
To read an XML file you have to create a temporary structure and a Node list. Then the XML file is loaded as a Filestream. The xmldoc.GetElementsByTagName(NodeName) can be used to load the Nodes into the struct.
xmlnode.Count returns the count of elements with the former set TagName. Now you are able to select the ChildNodes aka Item assigned to the rootNode.
xmlnode[0].CHildNodes.Item(0).InnerText returns the value of the first (0) ChildNode that is assigned to the first (0) occurence of the rootNode. Since we do set up the XML files, we do know which Item contains which information.
At the end, the Filestream must be closed by fs.close() to stop blocking the XML file.
Downloads
Adding Different Dialoges
For proper usabillity I had to add a few Message-Boxes and an additional dialoge. Also I used the "FolderBrowserDialog" and "openFileDialog" which I like to explain here.
Handling of "MessageBox":
DialogResult dialogResult = MessageBox.Show("This is a warning!!", "Warning", MessageBoxButtons.YesNo); if (dialogResult == DialogResult.Yes) { //This is executed when the MessageBox is closed with "OK" } else if (dialogResult == DialogResult.No) { //do something else }
MessageBox.Show("This is my Text") shows a Message that must be closed with "OK". I use this a lot for Warning or Information for exception handling.
By adding the DialogResult, you are able to react depending the users choice. That is needed when someting could be deleted for example.
Usage of "FolderBrowserDialog":
if (folderBrowserDialog1.ShowDialog() == DialogResult.OK) { RootPath = folderBrowserDialog1.SelectedPath; textBox2.Text = folderBrowserDialog1.SelectedPath; }
folderBrowserDialog1.ShowDialog() opens the folder browse dialog and returns the Dialog result which directly can be evaluated. The selected folder path is returned as folderBrowserDialog1.SelectedPath.
How to use "openFileDIalog":
//Select Picture Dialoge openFileDialog1.Filter = "Image files |*.png;*.jpg;*.jpeg;*.bmp| All files |*.*"; openFileDialog1.FilterIndex = 2; DialogResult = openFileDialog1.ShowDialog(); if (DialogResult == DialogResult.OK) { //This will be done when Dialog was closed with "OK" } else { //This will be executed when the window is closed without a proper selection MessageBox.Show("No Image selected"); }
openFileDialog1.Filter sets the filetypes that are selectable within the dialog. You have to follow my example to use several filetypes in a single filter.
openFileDialog1.FilterIndex = 2 activates the filter.
DialogResult = openFileDialog1.ShowDialog() returns the result of the dialog which then is used to execute code dependent of the result
Adding an additional Form:
Form2 testDialog = new Form2(); //This sets up the "Form2" as testDialog ... testDialog.listView1.Items.Add(Dir,fullName); //You are able to interact with the testDialog functions if (testDialog.ShowDialog(this) == DialogResult.OK) //Show Dialog and evaluate result { // Read the contents of testDialog's TextBox. ListView.SelectedListViewItemCollection project = testDialog.listView1.SelectedItems; //Get further result ... testDialog.Dispose(); //Close dialog }
The Form2 must be added to the Project and then can be designed with the toolbox. Within the program you have to add a temporary dialog and are able to interact with the functions that are shown on form2.
testDialog.ShowDialog(this) shows the dialog and returns the DialogResult.
testDialog.Dispose() is needed to close the dialog.
Handling of Picturebox
I wanted the possibility to add a picture of my creation to the program, therefore I used the "pictureBox" functionality. To add that function was really easy, but it was hard (at least for me) to figure out a way to exchange the images or to delete the project.
Once an image is opened directly in a pictureBox it is impossible to delete or overwrite the root file. The file itself is blocked by the program. I searched the web for a solution, and found the following, which worked for me:
FileStream fsimg = new FileStream(ProjectPath + @"\" + xmlnode[i].ChildNodes.Item(3).InnerText.Trim(), FileMode.Open, FileAccess.Read); pictureBox1.Image = System.Drawing.Image.FromStream(fsimg); fsimg.Close();
It is necessary to read in the Image as a Filestream.
Therefore I use FileStream fsimg = new FileStream(ImagePath, FileMode.Open, FileAccess.Read);
pictureBox1.Image = System.Drawing.Image.FromStream(fsimg) is drawing the image from the Filestream.
fsimg.Close() Closes the Filestream again to unblock the file in the filesystem.
if (pictureBox3.Image != null) { pictureBox3.Image.Dispose(); } pictureBox3.Image = null; Directory.Delete(RootPath + @"\" + textBox4.Text,true);
To reset the Image, just set the pictureBox.Image = null, then the pictureBox is empty again. Now the file itself can be deleted.
File Dropper With "Automatic" File Mover
That is one of the main features I needed to have. Therefore I added a listBox and activated the "AllowDrop"-Function.
Also I had to add the following code:
public Form1() { InitializeComponent(); this.listBox1.DragDrop += new System.Windows.Forms.DragEventHandler(this.listBox1_DragDrop); this.listBox1.DragEnter += new System.Windows.Forms.DragEventHandler(this.listBox1_DragEnter); }
listBox1.DragEnter ist the function to move something onto the listBox and listBox1.DragDrop will be executed when a file is droppen onto the listBox.
Then both functions must be added:
private void listBox1_DragEnter(object sender, System.Windows.Forms.DragEventArgs e) { if (e.Data.GetDataPresent(DataFormats.FileDrop)) { e.Effect = DragDropEffects.All; } else { e.Effect = DragDropEffects.None; } private void listBox1_DragDrop(object sender, System.Windows.Forms.DragEventArgs e) { string[] s = (string[])e.Data.GetData(DataFormats.FileDrop, false); int i; for (i = 0; i < s.Length; i++) { listBox1.Items.Add(s[i]); } }
Within the listBox1_DragEnter() you have the possibility to check wether a filetype is allowed to be dropped or not. In my case, all Files are allowed.
The function listBox1_DragDrop() adds all dropped files to the listBox Items.
Also I added two buttons to move the files and delete wrong entries:
private void button7_Click(object sender, EventArgs e) { //File dropper file mover Browse Tab if (SelectedProject != "Selected Project") { foreach (string item in listBox1.Items) { string ext = Path.GetExtension(item); foreach (TreeNode treeNode in treeView1.Nodes[0].Nodes) { if (treeNode.Name.Contains(ext)) { if (File.Exists(item)) { if(Directory.Exists(ProjectPath + @"\" + treeNode.Text)) { File.Move(item, ProjectPath + @"\" + treeNode.Text + @"\" + item.Substring(item.LastIndexOf(@"\") + 1)); } else { Directory.CreateDirectory(ProjectPath + @"\" + treeNode.Text); File.Move(item, ProjectPath + @"\" + treeNode.Text + @"\" + item.Substring(item.LastIndexOf(@"\") + 1)); } } } } if (File.Exists(item)) { File.Move(item, ProjectPath + @"\" + item.Substring(item.LastIndexOf(@"\") + 1)); } } listBox1.Items.Clear(); } } private void button8_Click(object sender, EventArgs e) { //Delete File dropper entry if (listBox1.SelectedIndex != -1) { listBox1.Items.RemoveAt(listBox1.SelectedIndex); } }
OnceButton 7 is clicked, the function button7_Click() is executed. That function checks if the necessary folders do exist and moves the files depending on the filetypes.
Path.GetExtension(File-Path) returns the Files extension and if the next if (treeNode.Name.Contains(extension)) returns true, the file is moved to the directory of the selected treeNode.Text.
For example, the treeNode.Text is "Pictures" and equals the directory, while the treeNode.Name contains the filetypes, for example "*.png*. If the extension of the file is ".png", the file will be moved to the "Pictures" folder.
button8_Click deletes the item with the index of the selected item.
listBox1.SelectedIndex() returns the Index of the selected item within the listBox1.Items.
To avoid exceptions, the listBox1.SelectedIndex must not be "-1" which means "None selected".
How to Use the OrgaNicer
After you started the Program, you will be able to switch between the three Main Tabs:
Browse:
Within the Browse Tab you can easily browse through all your former created Projects. To select a Project, you have the possibility to search for the Project Name or for some specific Keywords that are assigned to that project.
When you have selected a Project you can see all the details, keywords and an image of your creation.
Here you have the possibility to modify the keywords, the description or the image. Also you can easily add files to the project, that get automatically sorted into the subdirectories, depending on the extension.
Also you have the possibility to open the project directory directly in windows explorer.
Create:
Here you are able to create the Project by just writing a Name into the required field and click on "Create". The program automatically creates the necessary folder structure and the xml file.
After the project is created, you can add further files by dropping them onto the file dropper.
Also you have the possibility to add keywords, description and an image to the newly created project.
Settings:
In the Settings page you have to select the root Projects folder and set up the subdirectory that should be created also.
Therefore just insert the name of the subdirectory to the field and click on "Add Subfolder". Also you have the possibility to set up the file sorter filetypes by adding them into the textbox.