/// <summary>
        /// Set up the enabled Skills tree.
        /// </summary>
        private void UpdateSkillsTree()
        {
            tvSkills.BeginUpdate();
            try
            {
                tvSkills.Nodes.Clear();
                if (m_skill == null)
                    return;

                for (int i = 1; i <= 5; i++)
                {
                    SkillLevel skillLevel = new SkillLevel(m_skill, i);

                    // Gets the enabled skills and check it's not empty
                    Skill[] enabledSkills = m_skill.Character.Skills.Where(x => x.Prerequisites.Any(y => y.Skill == m_skill && y.Level == i) && x.IsPublic).ToArray();
                    if (enabledSkills.IsEmpty())
                        continue;

                    // Add a node for this skill level
                    TreeNode levelNode = new TreeNode(skillLevel.ToString());
                    if (m_skill.Level >= i)
                        levelNode.Text += " (Trained)";

                    levelNode.ForeColor = Color.DarkBlue;

                    // Is it a plain alphabetical presentation ?
                    if (rbShowAlpha.Checked)
                    {
                        foreach (Skill skill in enabledSkills.OrderBy(x => x.Name))
                        {
                            levelNode.Nodes.Add(CreateNode(skill, skill.Prerequisites));
                        }
                    }
                    // Or do we need to group skills by their groups ?
                    else if (rbShowTree.Checked)
                    {
                        foreach (IGrouping<SkillGroup, Skill> group in enabledSkills
                            .GroupBy(x => x.Group).ToArray().OrderBy(x => x.Key.Name))
                        {
                            TreeNode groupNode = new TreeNode(group.Key.Name);
                            foreach (Skill skill in group.ToArray().OrderBy(x => x.Name))
                            {
                                groupNode.Nodes.Add(CreateNode(skill, skill.Prerequisites));
                            }
                            levelNode.Nodes.Add(groupNode);
                        }
                    }

                    // Add node
                    levelNode.Expand();
                    tvSkills.Nodes.Add(levelNode);
                }

                // No enabled skill found for any level ?
                if (tvSkills.Nodes.Count == 0)
                    tvSkills.Nodes.Add(new TreeNode("No skills enabled by this skill"));

            }
            finally
            {
                tvSkills.EndUpdate();
            }
        }
        /// <summary>
        /// Helper method for the Show Prereqs menu used by both ship and item trees.
        /// This method adds one prereq to the string that will be displayed in the
        /// dialog box.
        /// </summary>
        /// <param name="sb">The StringBuilder object.</param>
        /// <param name="prereq">The prereq</param>
        /// <param name="index">The index.</param>
        private void FormatPrerequisite(StringBuilder sb, SkillLevel prereq, ref int index)
        {
            if (prereq.Skill.IsKnown)
            {
                // We know this prereq, but not to a high enough level
                if (!prereq.IsKnown)
                {
                    index++;
                    string level = prereq.Skill.Level > 0 ? String.Format(CultureConstants.DefaultCulture, "(Trained to level {0})", prereq.Skill.RomanLevel) : "(Not yet trained)";
                    sb.AppendFormat(CultureConstants.DefaultCulture, "{0}. {1} {2}\n", index, prereq.ToString(), level);
                }
                return;
            }

            // We don't know this prereq at all
            index++;
            sb.AppendFormat(CultureConstants.DefaultCulture, "{0}. {1} (Prereqs {2}met, skillbook {3}", index, prereq.ToString(),
                (prereq.Skill.Prerequisites.AreTrained() ? String.Empty : "not "),
                (prereq.Skill.IsOwned ? "owned)": String.Format(CultureConstants.DefaultCulture, "not owned,\n costs {0} ISK)\n", prereq.Skill.FormattedCost)));
        }
        /// <summary>
        /// Set up the items/ships/blueprints tree.
        /// </summary>
        private void UpdateItemsTree()
        {
            m_hasShips = false;
            m_hasItems = false;
            m_hasBlueprints = false;

            tvEntity.BeginUpdate();
            try
            {
                tvEntity.Nodes.Clear();
                if (m_skill == null)
                    return;

                List<Item> items = new List<Item>(StaticItems.AllItems.Concat(StaticBlueprints.AllBlueprints).
                    Where(x => x.MarketGroup.ParentGroup != null && x.MarketGroup.ParentGroup.ID != DBConstants.SkillGroupID). // exclude skills
                    Where(x => x.Prerequisites.Any(y => y.Skill == m_skill.StaticData)).
                    Where(x => !cbShowBaseOnly.Checked || x.MetaGroup == ItemMetaGroup.T1 || x.MetaGroup == ItemMetaGroup.T2));

                // Scroll through levels
                for (int i = 1; i <= 5; i++)
                {
                    SkillLevel skillLevel = new SkillLevel(m_skill, i);

                    // Gets the enabled objects and check it's not empty
                    IEnumerable<Item> enabledObjects = items.Where(x => x.Prerequisites.Any(y => y.Skill == m_skill.StaticData && y.Level == i));
                    if (enabledObjects.IsEmpty())
                        continue;

                    // Add a node for this skill level
                    TreeNode levelNode = new TreeNode(skillLevel.ToString());
                    if (m_skill.Level >= i)
                        levelNode.Text += " (Trained)";

                    levelNode.ForeColor = Color.DarkBlue;

                    // Is it a plain alphabetical presentation ?
                    if (rbShowAlpha.Checked)
                    {
                        foreach (Item ship in enabledObjects.Where(x => x is Ship).ToArray().OrderBy(x => x.Name))
                        {
                            levelNode.Nodes.Add(CreateNode(ship, ship.Prerequisites.ToCharacter(m_character)));
                            m_hasShips = true;
                        }

                        foreach (Item blueprint in enabledObjects.Where(x => x is Blueprint).ToArray().OrderBy(x => x.Name))
                        {
                            List<string> listOfActivities = blueprint.Prerequisites.Where(x => x.Skill == m_skill.StaticData && x.Level == i)
                                                                        .Select(x => x.Activity.GetDescription()).ToList();
                            TreeNode node = CreateNode(blueprint, blueprint.Prerequisites
                                .Where(x => listOfActivities.Contains(x.Activity.GetDescription())).ToCharacter(m_character));
                            node.Text = String.Format("{0} ({1})", node.Text, string.Join(", ", listOfActivities));
                            levelNode.Nodes.Add(node);
                            m_hasBlueprints = true;
                        }

                        foreach (Item item in enabledObjects.Where(x => !(x is Ship) && !(x is Blueprint)).ToArray().OrderBy(x => x.Name))
                        {
                            levelNode.Nodes.Add(CreateNode(item, item.Prerequisites.ToCharacter(m_character)));
                            m_hasItems = true;
                        }
                    }
                    // Or do we need to group items by their groups ?
                    else if (rbShowTree.Checked)
                    {
                        // Add ships
                        IGrouping<MarketGroup, Item>[] shipsToAdd = enabledObjects.Where(x => x is Ship).GroupBy(x => x.MarketGroup.ParentGroup).ToArray();
                        foreach (IGrouping<MarketGroup, Item> shipGroup in shipsToAdd.OrderBy(x => x.Key.Name))
                        {
                            TreeNode groupNode = new TreeNode(shipGroup.Key.Name);
                            foreach (Item ship in shipGroup.ToArray().OrderBy(x => x.Name))
                            {
                                groupNode.Nodes.Add(CreateNode(ship, ship.Prerequisites.ToCharacter(m_skill.Character)));
                            }
                            levelNode.Nodes.Add(groupNode);
                            m_hasShips = true;
                        }

                        // Add blueprints recursively
                        foreach (BlueprintMarketGroup blueprintMarketGroup in StaticBlueprints.BlueprintMarketGroups)
                        {
                            foreach (TreeNode node in CreateMarketGroupsNode(blueprintMarketGroup, enabledObjects.Where(x => x is Blueprint), i))
                            {
                                levelNode.Nodes.Add(node);
                                m_hasBlueprints = true;
                            }
                        }

                        // Add items recursively
                        foreach (MarketGroup marketGroup in StaticItems.MarketGroups)
                        {
                            foreach (TreeNode node in CreateMarketGroupsNode(marketGroup, enabledObjects.Where(x => !(x is Ship) && !(x is Blueprint))))
                            {
                                levelNode.Nodes.Add(node);
                                m_hasItems = true;
                            }
                        }
                    }

                    // Add node
                    levelNode.Expand();
                    tvEntity.Nodes.Add(levelNode);
                }

                // No enabled skill found for any level ?
                if (tvEntity.Nodes.Count == 0)
                    tvEntity.Nodes.Add(new TreeNode("No ships, blueprints or items enabled by this skill"));
            }
            finally
            {
                tvEntity.EndUpdate();
            }
        }
        /// <summary>
        /// Create a node from a prerequisite skill
        /// </summary>
        /// <param name="skillPrereq"></param>
        /// <returns></returns>
        private TreeNode CreateNode(SkillLevel skillPrereq)
        {
            TreeNode node = new TreeNode();
            node.Text = skillPrereq.ToString();
            node.Tag = skillPrereq;

            // Add this skill's prerequisites
            foreach (var prereqSkill in skillPrereq.Skill.Prerequisites)
            {
                if (prereqSkill.Skill != skillPrereq.Skill)
                {
                    node.Nodes.Add(CreateNode(prereqSkill));
                }
            }

            return node;
        }