private void getChildRowCount (AggregateRow row, Grouping<GroupBy> childGrouping, TreeDataGridViewCellValueEventArgs e)
 {
     if (childGrouping == null)
     {
         if (checkedGroupings.Any(o => o.Mode == GroupBy.Spectrum || o.Mode == GroupBy.Peptide))
             e.HasChildRows = true;
         else
             e.ChildRowCount = row.PeptideSpectrumMatches;
     }
     else if (childGrouping.Mode == GroupBy.Source)
     {
         var dataFilter = row.DataFilter;
         if (dataFilter.SpectrumSourceGroup == null)
         {
             // create a filter from the cached root group for this data filter
             var nonGroupParentFilterKey = new DataFilterKey(dataFilter);
             var rootGroup = (getSpectrumSourceRows(dataFilter)[0] as SpectrumSourceGroupRow).SpectrumSourceGroup;
             dataFilter = new DataFilter(row.DataFilter) { SpectrumSourceGroup = new List<SpectrumSourceGroup>() { rootGroup } };
         }
         e.ChildRowCount = getSpectrumSourceRows(dataFilter).Count;
     }
     else if (childGrouping.Mode == GroupBy.Spectrum)
         e.ChildRowCount = row.Spectra;
     else if (childGrouping.Mode == GroupBy.Analysis)
         e.ChildRowCount = row.DistinctAnalyses;
     else if (childGrouping.Mode == GroupBy.Peptide)
         e.ChildRowCount = row.DistinctPeptides;
     else if (childGrouping.Mode == GroupBy.Charge)
         e.ChildRowCount = row.DistinctCharges;
     else
         throw new NotImplementedException();
 }
        private void treeDataGridView_CellValueNeeded (object sender, TreeDataGridViewCellValueEventArgs e)
        {
            if (e.RowIndexHierarchy.First() >= rows.Count)
            {
                e.Value = null;
                return;
            }

            Row baseRow = GetRowFromRowHierarchy(e.RowIndexHierarchy);

            Grouping<GroupBy> childGrouping = null;

            if (baseRow is SpectrumSourceGroupRow)
            {
                var row = baseRow as SpectrumSourceGroupRow;
                var nonGroupParentFilterKey = new DataFilterKey(new DataFilter(row.DataFilter) { SpectrumSourceGroup = null });

                var cachedRowsBySource = rowsBySource[nonGroupParentFilterKey];
                e.ChildRowCount = cachedRowsBySource.OfType<SpectrumSourceGroupRow>()
                                                    .Count(o => o.SpectrumSourceGroup.IsImmediateChildOf(row.SpectrumSourceGroup) /*&&
                                                                (findTextBox.Text == "Find..." || o.SpectrumSourceGroup.Name.Contains(findTextBox.Text))*/);
                e.ChildRowCount += cachedRowsBySource.OfType<SpectrumSourceRow>()
                                                     .Count(o => o.SpectrumSource.Group != null &&
                                                                 o.SpectrumSource.Group.Id == row.SpectrumSourceGroup.Id /*&&
                                                                 (findTextBox.Text == "Find..." || o.SpectrumSource.Name.Contains(findTextBox.Text))*/);

                if (e.ChildRowCount == 0 && findTextBox.Text == "Find...")
                    throw new InvalidDataException("no child rows for source group");
            }
            else if (baseRow is SpectrumSourceRow)
                childGrouping = GroupingSetupControl<GroupBy>.GetChildGrouping(checkedGroupings, GroupBy.Source);
            else if (baseRow is SpectrumRow)
                childGrouping = GroupingSetupControl<GroupBy>.GetChildGrouping(checkedGroupings, GroupBy.Spectrum);
            else if (baseRow is AnalysisRow)
                childGrouping = GroupingSetupControl<GroupBy>.GetChildGrouping(checkedGroupings, GroupBy.Analysis);
            else if (baseRow is PeptideRow)
                childGrouping = GroupingSetupControl<GroupBy>.GetChildGrouping(checkedGroupings, GroupBy.Peptide);
            else if (baseRow is ChargeRow)
                childGrouping = GroupingSetupControl<GroupBy>.GetChildGrouping(checkedGroupings, GroupBy.Charge);
            else if (baseRow is PeptideSpectrumMatchRow)
                e.HasChildRows = true;

            if (!e.ChildRowCount.HasValue && baseRow is AggregateRow)
                getChildRowCount(baseRow as AggregateRow, childGrouping, e);

            e.Value = getCellValue(e.ColumnIndex, baseRow);
        }
        // returns both groups and sources
        IList<Row> getSpectrumSourceRows (DataFilter parentFilter)
        {
            var nonGroupParentFilterKey = new DataFilterKey(new DataFilter(parentFilter) { SpectrumSourceGroup = null });

            if (!rowsBySource.ContainsKey(nonGroupParentFilterKey))
                lock (session)
                {
                    var groupsFilter = new DataFilter(parentFilter) { SpectrumSourceGroup = null };
                    var groups = session.CreateQuery(AggregateRow.Selection + ", ssgl " +
                                                     groupsFilter.GetFilteredQueryString(DataFilter.FromPeptideSpectrumMatch,
                                                                                         DataFilter.PeptideSpectrumMatchToProtein,
                                                                                         DataFilter.PeptideSpectrumMatchToSpectrumSourceGroupLink) +
                                                     "GROUP BY ssgl.Group.id")
                        .List<object[]>()
                        .Select(o => new SpectrumSourceGroupRow(o, parentFilter))
                        .ToList();

                    var sources = session.CreateQuery(AggregateRow.Selection + ", s.Source " +
                                                      parentFilter.GetFilteredQueryString(DataFilter.FromPeptideSpectrumMatch,
                                                                                          DataFilter.PeptideSpectrumMatchToProtein,
                                                                                          DataFilter.PeptideSpectrumMatchToSpectrum) +
                                                      "GROUP BY s.Source.id")
                        .List<object[]>()
                        .Select(o => new SpectrumSourceRow(o, parentFilter))
                        .ToList();

                    rowsBySource[nonGroupParentFilterKey] = groups.Cast<Row>().Concat(sources.Cast<Row>()).ToList();
                }

            var ssgRows = rowsBySource[nonGroupParentFilterKey].OfType<SpectrumSourceGroupRow>();
            var ssRows = rowsBySource[nonGroupParentFilterKey].OfType<SpectrumSourceRow>();
            var result = Enumerable.Empty<Row>();

            if (parentFilter != null && parentFilter.SpectrumSourceGroup != null)
                foreach (var item in parentFilter.SpectrumSourceGroup)
                    result = result.Concat(ssgRows.Where(o => o.SpectrumSourceGroup.IsImmediateChildOf(item) /*&&
                                                              (findTextBox.Text == "Find..." || o.SpectrumSourceGroup.Name.Contains(findTextBox.Text))*/).Cast<Row>());
            else
                result = ssgRows.Where(o => o.SpectrumSourceGroup.Name == "/").Cast<Row>();

            if (parentFilter != null && parentFilter.SpectrumSourceGroup != null)
            {
                foreach (var item in parentFilter.SpectrumSourceGroup)
                    result = result.Concat(ssRows.Where(o => o.SpectrumSource.Group != null &&
                                                             o.SpectrumSource.Group.Id == item.Id /*&&
                                                             (findTextBox.Text == "Find..." || o.SpectrumSource.Name.Contains(findTextBox.Text))*/).Cast<Row>());
            }

            return result.ToList();
        }