/// <summary> /// Set prune, remove from listBox and set to prunelist /// </summary> public List <PartEntry> PruneFile(PartEntry entry, bool prune) { string path = null; path = CreatePruneEntry(entry); // set/unset pruned if (prune) { if (UnPruneList.Contains(path)) { UnPruneList.Remove(path); PrintMessage("Remove Unprune path: " + path); } else { PruneList.Add(path); PrintMessage("Add prune path: " + path); } } else { if (PruneList.Contains(path)) { PruneList.Remove(path); PrintMessage("Remove prune path: " + path); } else { UnPruneList.Add(path); PrintMessage("Add Unprune path: " + path); } } var changed = new List <PartEntry>(); foreach (PartEntry pe in PartEntries) { if (pe.Path.StartsWith(path)) { Debug.Assert(pe.Pruned != prune); if (pe.Pruned != prune) { pe.Pruned = prune; NofPrunedParts += prune ? 1 : -1; changed.Add(pe); } } } SavePruneList(_prunePath, PruneList); SavePruneList(_unprunePath, UnPruneList); return(changed); }
/// <summary> /// Returns true if the given part is the only thing /// specified in its cfg file, any other thing (or its parent part) is /// pruned /// </summary> /// <param name="pe"></param> /// <returns></returns> private bool IsOnlyEntry(PartEntry pe, List <string> pruneNames) { foreach (PartEntry other in PartEntries) { if (!other.Pruned && pe != other && other.Path.Equals(pe.Path)) { // allow, if all parts are pruned if (!((other.IsMod && pruneNames.Contains(other.Parent)) || (!other.IsMod && pruneNames.Contains(other.Name)))) { return(false); } } } return(true); }
// open right cklick menu private void listBox_MouseDown(object sender, MouseEventArgs e) { if (e.Button != MouseButtons.Right) { return; } ListBox listBox = (ListBox)sender; listBox.SelectedIndex = listBox.IndexFromPoint(e.Location); if (listBox.SelectedIndex != -1) { _selectedPartEntry = (PartEntry)listBox.Items[listBox.SelectedIndex]; contextMenuStrip1.Show(); } else { _selectedPartEntry = null; } }
/// <summary> /// If a part shall be pruned, this creates the best entry for a prune /// file. /// </summary> /// <param name="entry"></param> /// <returns></returns> private static string CreatePruneEntry(PartEntry entry) { string path; // subdirectory string partPath = entry.FullPath.Substring(0, entry.FullPath.LastIndexOf("\\")); var cfgs = Functions.FindFilesRec(partPath, ".cfg"); var prunedCfgs = Functions.FindFilesRec(partPath, ".cfg.pruned"); if (cfgs.Count + prunedCfgs.Count == 1) { path = entry.Path.Substring(0, entry.Path.LastIndexOf("\\")); } else { // add the path without the ending, so all files with the same prefix will be pruned path = entry.Path.Substring(0, entry.Path.LastIndexOf("cfg")); } return(path); }
private void PruneFile(PartEntry entry, bool prune) { if (_finder == null) { return; } var changed = _finder.PruneFile(entry, prune); var removeFrom = prune ? listBoxParts : listBoxPruned; var addTo = !prune ? listBoxParts : listBoxPruned; // consider every part associated with the path foreach (PartEntry pe in changed) { if (pe.IsDeletion) { if (checkBoxNoDeleted.Checked) { List <PartEntry> deleted; if (_finder.PartDict.TryGetValue(pe.Parent, out deleted) && deleted != null) { foreach (var d in deleted) { // if mod/copy if ((d.IsMod && checkBoxNoMods.Checked) || (d.IsCopy && checkBoxNoCopies.Checked) || (d.Name.Contains("*") && checkBoxNoWild.Checked)) { continue; } if (prune) { // remove the effects of the deletion if (d.Pruned) { listBoxPruned.Items.Add(d); } else { listBoxParts.Items.Add(d); } } else { // add the effects of deleting // remove the effects of the deletion if (d.Pruned) { listBoxPruned.Items.Remove(d); } else { listBoxParts.Items.Remove(d); } } } } } } else { Debug.Assert(pe.Pruned == prune); // remove ad from the respective list box if ((_search == null || pe.MatchesPattern(_search) && (!pe.IsMod || !checkBoxNoMods.Checked) && (!pe.IsCopy || !checkBoxNoCopies.Checked))) { removeFrom.Items.Remove(pe); addTo.Items.Add(pe); } } } if (changed.Count > 0) { PrintMessage((prune ? "pruned " : "unpruned ") + changed.Count + " parts"); } // since we chaned something UpdateLabel(); }
public void SearchStuff() { PrintMessage("read prune list ..."); string err; PruneList = Functions.ReadPruneList(_prunePath, out err); if (err != null) { PrintMessage(err); UnPruneList = new List <string>(); } UnPruneList = Functions.ReadPruneList(_unprunePath, out err); if (err != null) { PrintMessage(err); UnPruneList = new List <string>(); } PrintMessage("searching ..."); // find all parts in the files files var files = Functions.FindFilesRec(_installPath + "\\GameData", ".cfg"); var prunedFiles = Functions.FindFilesRec(_installPath + "\\GameData", ".cfg.pruned"); PrintMessage("found " + (files.Count + prunedFiles.Count) + " files (" + prunedFiles.Count + " pruned) ..."); PrintMessage("extracting names ..."); // creating entries PartEntries = new List <PartEntry>(); NofPrunedParts = 0; // get them parts from the files foreach (string f in files) { var add = ExtractParts(f, false); PartEntries.AddRange(add); } foreach (string f in prunedFiles) { PartEntries.AddRange(ExtractParts(f, true)); } // create hash set PartDict = new Dictionary <string, List <PartEntry> >(); foreach (PartEntry entry in PartEntries) { if (entry.Name != null) { string name = (entry.IsDeletion ? "!" : "") + entry.Name; //if ((name == null || name.Length == 0) && entry.Parent != null && entry.Parent.Length > 0) //{ // name = entry.Parent; // entry.Name = name; //} if (name.Length > 0) { List <PartEntry> l; if (!PartDict.TryGetValue(name, out l)) { l = new List <PartEntry>(); PartDict.Add(name, l); } l.Add(entry); } } } // post process foreach (PartEntry entry in PartEntries) { bool pruned = entry.Pruned; // check wheter the part is on the prune list if (!pruned) { foreach (string prune in PruneList) { if (entry.Path.StartsWith(prune)) { pruned = true; break; } } } // check wheter the part is on the unprune list if (pruned) { foreach (string prune in UnPruneList) { if (entry.Path.StartsWith(prune)) { pruned = false; break; } } } entry.Pruned = pruned; if (pruned) { NofPrunedParts++; } // add titles to the parts // find root PartEntry root = entry; while (root.Parent != null) { // search the parent List <PartEntry> parent; PartDict.TryGetValue(root.Parent, out parent); if (parent != null) { // pick the most parentiest parent PartEntry pick = null; foreach (var p in parent) { if (pick == null || (!p.IsDeletion && (pick.IsMod || !p.IsMod) && (pick.IsReplace || !p.IsReplace) && (pick.IsCopy || !p.IsCopy && pick.Parent != null))) { pick = p; } } // if on the same level do not continue if (root.Parent.Equals(pick.Parent)) { root = null; break; } root = pick; } else { root = null; break; } } // now we found the root if (root != entry && root != null) { // use the parents name //if (entry.Name == null || entry.Name.Length == 0) //{ // entry.Name = entry.Parent; //} // add the title to the root not if (root.TitleFamily == null) { root.TitleFamily = new List <string>(); } // share the list entry.TitleFamily = root.TitleFamily; bool already = false; foreach (string s in root.TitleFamily) { if (root.Equals(s)) { already = true; break; } } if (!already && entry.Title != null) { root.TitleFamily.Add(entry.Title); } } } // output status PrintMessage("found " + PartEntries.Count + " results (" + NofPrunedParts + " pruned) ..."); PrintMessage("sorting ..."); // sort results PartEntries = PartEntries.OrderBy((PartEntry x) => { return(x.Name); }).ToList(); PrintMessage("printing ..."); NeedsUpdate = false; }
/// <summary> /// returns all parts created by the given list /// </summary> /// <param name="path"></param> /// <returns></returns> private List <PartEntry> ExtractParts(string path, bool pruned) { var entries = new List <PartEntry>(); int subPathStart = path.IndexOf("\\GameData\\") + 10; int subPathEnd = path.LastIndexOf("\\"); string subPath = path.Substring(subPathStart, subPathEnd - subPathStart + 1); string fileName = path.Substring(path.LastIndexOf("\\") + 1); // open the file FileStream fs = null; StreamReader sr = null; try { fs = new FileStream(path, FileMode.Open); sr = new StreamReader(fs); // parse the file var current = new List <PartEntry>(); string l; string todo = null; int partIndent = -1; // the indent level of the current part bool wasInPartBody = false; int indent = 0; do { #region READLINE & INDENTION // readline and indention if (todo != null) { l = todo; todo = null; } else { l = sr.ReadLine(); int commentStart = l.IndexOf("//"); if (commentStart != -1) { l = l.Substring(0, commentStart); } } // TODO: this is possibly never ever tested while (true) { if (l.Contains('{') || l.Contains('}')) { int brace = l.IndexOf('{'); int braceR = l.IndexOf('}'); brace = brace == -1 || (braceR != -1 && braceR < brace) ? braceR : brace; if (brace != -1) { if (brace == 0) { indent += l[0] == '{' ? 1 : -1; l = l.Substring(1); } else { string left = l.Substring(0, brace); string right = l.Substring(brace); left = left.Trim(); l = left; todo = right; } } } else { break; } } // shortcut if (l.Length == 0) { continue; } #endregion //Debug.WriteLine(indent + ": " + l); #region PART DEFINITION var trimmed = l.Trim(); if (indent == 0 && (trimmed.Equals("PART") || (trimmed.Length > 4 && trimmed.Substring(1).StartsWith("PART[")))) { var parentNames = new List <string>();; int oNameStart = l.IndexOf("["); if (oNameStart != -1) { oNameStart++; int oNameEnd = l.IndexOf("]"); if (oNameEnd == -1) { oNameEnd = l.Length; } string names = l.Substring(oNameStart, oNameEnd - oNameStart); parentNames.AddRange(names.Split(',', '|')); } else { parentNames.Add(null); } current = new List <PartEntry>(); for (int i = 0; i < parentNames.Count; i++) { var c = new PartEntry(subPath + fileName, path); c.Name = parentNames[i]; c.Parent = parentNames[i]; c.Pruned = pruned; current.Add(c); entries.Add(c); } partIndent = indent + 1; wasInPartBody = false; if (l.Contains("!PART") || l.Contains("-PART")) { foreach (var c in current) { c.IsDeletion = true; } partIndent = -1; // ignore the node //current = new List<PartEntry>(); } else if (l.Contains("@PART")) { foreach (var c in current) { c.IsMod = true; } } else if (l.Contains("+PART") || l.Contains("$PART")) { foreach (var c in current) { c.IsCopy = true; } } else if (l.Contains("%PART")) { foreach (var c in current) { c.IsReplace = true; } } else if (l.Contains("|PART")) { throw new NotImplementedException(); } else if (l.Contains("%PART")) { throw new NotImplementedException(); } else if (l.Contains("#PART")) { throw new NotImplementedException(); } else if (l.Contains("*PART")) { throw new NotImplementedException(); } } #endregion // ignore anything inside and outside parts if (indent < partIndent) { if (wasInPartBody) { partIndent = -1; } continue; } wasInPartBody = true; //Debug.WriteLine(indent + ": " + l); #region PARSE ENTRIES string resPath = null; if (indent == partIndent) { // title { string title = ParseLine(l, "title"); if (title != null) { foreach (var c in current) { c.Title = title; } } } // name { string name = ParseLine(l, "name"); if (name != null) { foreach (var c in current) { c.Name = name; } } } } else if (indent == partIndent + 1) { // model { string model = ParseLine(l, "model"); if (model != null) { resPath = model; } } // texture { string texture = ParseLine(l, "texture"); if (texture != null) { if (texture.Contains(",")) { texture = texture.Substring(texture.IndexOf(",") + 1).Trim(); } resPath = texture; } } } if (resPath != null) { resPath = resPath.Replace("/", "\\"); // if relative path if (!resPath.Contains("\\")) { resPath = subPath + resPath; } var resPathes = GetResourcePaths(resPath); foreach (var c in current) { c.Resources.Add(resPath); } } #endregion } while (!sr.EndOfStream); return(entries); } catch (Exception ex) { Debug.WriteLine(ex); return(new List <PartEntry>()); // "_XX file not found (" + ex + ")XX"; } finally { if (fs != null) { fs.Close(); } } }