1bbbf05971f950d48fcd67ac9e8e6d395bae9761
braney
  Tue Mar 10 09:29:23 2026 -0700
fix problem with composites with only one child and noParentConfig on (refs #37130)

diff --git src/hg/lib/hui.c src/hg/lib/hui.c
index 673443e7f36..a00bad8fdf6 100644
--- src/hg/lib/hui.c
+++ src/hg/lib/hui.c
@@ -4930,32 +4930,34 @@
 // End wrapper table for collapsible sections:
 puts("</TABLE>");
 
 wigOption(cart, name, title, leafTdb);
 
 cfgEndBox(boxed);
 }
 
 void cfgByCfgType(eCfgType cType,char *db, struct cart *cart, struct trackDb *tdb,char *prefix,
 	      char *title, boolean boxed)
 // Methods for putting up type specific cfgs used by composites/subtracks in hui.c
 {
 // When only one subtrack, then show it's cfg settings instead of composite/view level settings
 // This simplifies the UI where hgTrackUi won't have 2 levels of cfg,
 // while hgTracks still supports rightClick cfg of the subtrack.
+// Don't do this if noParentConfig is specified in the composite parent
+boolean noParentConfig = tdb && trackDbSetting(tdb, "noParentConfig");
 
-if (configurableByAjax(tdb,cType) > 0) // Only if subtrack's configurable by ajax do we
+if (!noParentConfig && (configurableByAjax(tdb,cType) > 0)) // Only if subtrack's configurable by ajax do we
     {                                  // consider this option
     if (tdbIsComposite(tdb)                       // called for the composite
         && !isCustomComposite(tdb)
         && !tdbIsCompositeView(tdb->subtracks)        // and there is no view level
         && slCount(tdb->subtracks) == 1)              // and there is only one subtrack
 	{
 	tdb = tdb->subtracks; // show subtrack cfg instead
 	prefix = tdb->track;
 	}
     else if (tdbIsSubtrack(tdb)                   // called with subtrack
 	 && tdbIsCompositeView(tdb->parent)       // subtrack has view
 	 && differentString(prefix,tdb->track)    // and this has been called FOR the view
 	 && slCount(tdb->parent->subtracks) == 1) // and view has only one subtrack
 	prefix = tdb->track; // removes reference to view level
     }
@@ -5329,30 +5331,31 @@
     puts("<TBODY>");
     }
 
 // Finally the big "for loop" to list each subtrack as a table row.
 printf("\n<!-- ----- subtracks list ----- -->\n");
 membersForAll_t* membersForAll = membersForAllSubGroupsGet(parentTdb,NULL);
 struct hash *vocabHash = vocabBasicFromSetting(parentTdb, cart);
 struct slRef *subtrackRef;
 
 /* Color handling ?? */
 //char *colors[2]   = { COLOR_BG_DEFAULT,
 //                      COLOR_BG_ALTDEFAULT };
 char *colors[2]   = { "bgLevel1",
 		  "bgLevel1" };
 int colorIx = settings->bgColorIx;
+boolean noParentConfig = parentTdb && trackDbSetting(parentTdb, "noParentConfig");
 
 for (subtrackRef = subtrackRefList; subtrackRef != NULL; subtrackRef = subtrackRef->next)
     {
     struct trackDb *subtrack = subtrackRef->val;
     int ix;
 
     // Determine whether subtrack is checked, visible, configurable, has group membership, etc.
     int fourState = subtrackFourStateChecked(subtrack,cart);
     boolean checkedCB = fourStateChecked(fourState);
     boolean enabledCB = fourStateEnabled(fourState);
     boolean visibleCB = fourStateVisible(fourState);
     membership_t *membership = subgroupMembershipGet(subtrack);
     eCfgType cType = cfgNone;
     if (!tdbIsMultiTrack(parentTdb))  // MultiTracks never have configurable subtracks!
 	cType = cfgTypeFromTdb(subtrack,FALSE);
@@ -5366,31 +5369,31 @@
 	    {  // subtrack only configurable if more than one subtrack in view
 	       // find "view" in subgroup membership: e.g. "signal"
 	    if (-1 != (ix = stringArrayIx(membersForAll->members[dimV]->groupTag,
 					  membership->subgroups, membership->count)))
 		{
 		int ix2;                       // find "signal" in set of all views
 		if (-1 != (ix2 = stringArrayIx(membership->membership[ix],
 					       membersForAll->members[dimV]->tags,
 					       membersForAll->members[dimV]->count)))
 		    {
 		    if (membersForAll->members[dimV]->subtrackCount[ix2] < 2)
 			cType = cfgNone;
 		    }
 		}
 	    }
-	else if (slCount(subtrackRefList) < 2   // don't bother if there is a single subtrack
+	else if (!noParentConfig && slCount(subtrackRefList) < 2   // don't bother if there is a single subtrack without noParentConfig in the composite header
 	     && cfgTypeFromTdb(parentTdb,FALSE) != cfgNone) // but the composite is configurable.
 	    cType = cfgNone;
 	}
 
     if (sortOrder == NULL && !useDragAndDrop)
 	{
 	char **lastDivide = NULL;
 	dividers_t *dividers = dividersSettingGet(parentTdb);
 	if (dividers)
 	    lastDivide = needMem(sizeof(char*)*dividers->count);
 	if (membership && divisionIfNeeded(lastDivide,dividers,membership) )
 	    colorIx = (colorIx == COLOR_BG_DEFAULT_IX ? COLOR_BG_ALTDEFAULT_IX
 						      : COLOR_BG_DEFAULT_IX);
 	dividersFree(&dividers);
 	}