d1bc57639309864bb2665bd46eddfe75863f76e4
braney
  Tue Apr 23 16:42:54 2024 -0700
rearrange how we're doing hub groups.

diff --git src/hg/hgTracks/hgTracks.c src/hg/hgTracks/hgTracks.c
index 007e0df..8dc15a0 100644
--- src/hg/hgTracks/hgTracks.c
+++ src/hg/hgTracks/hgTracks.c
@@ -6897,37 +6897,34 @@
     rPropagateGroup(subtrack, group);
     }
 }
 
 static void groupTracks(struct track **pTrackList,
 	struct group **pGroupList, struct grp *grpList, int vis)
 /* Make up groups and assign tracks to groups.
  * If vis is -1, restore default groups to tracks. */
 {
 struct group *unknown = NULL;
 struct group *group, *list = NULL;
 struct hash *hash = newHash(8);
 struct track *track;
 struct trackRef *tr;
 struct grp* grps = hLoadGrps(database);
-struct grp* hubGrps = trackHubGetGrps();
 struct grp *grp;
 float minPriority = 100000; // something really large
 boolean foundMap = FALSE;
 
-grps = slCat(grps, hubGrps);
-
 /* build group objects from database. */
 for (grp = grps; grp != NULL; grp = grp->next)
     {
     if (sameString(grp->name, "map"))
         foundMap = TRUE;
     /* deal with group reordering */
     float priority = grp->priority;
     // we want to get the minimum priority over 1 (which is custom tracks)
     if ((priority > 1.0) && (priority < minPriority)) minPriority = priority;
     if (withPriorityOverride)
         {
         char cartVar[512];
         safef(cartVar, sizeof(cartVar), "%s.priority",grp->name);
         if (vis != -1)
             priority = (float)cartUsualDouble(cart, cartVar, grp->priority);
@@ -8028,31 +8025,30 @@
 	    if (avgWigMafLoad > 0)
 		{
 		hPrintf("<idiv style='color:red' >&nbsp; &nbsp; %s wiggle, load %d</idiv><br />\n",
 			    track->shortLabel, avgWigMafLoad);
 		}
 	    }
     }
 hPrintf("</span>\n");
 }
 
 void initTrackList()
 /* need to init tracklist, sometimes early */
 {
 if (!trackList)
     {
-    trackHubResetGrps();
     if (measureTiming)
 	measureTime("Time before getTrackList");
     boolean defaultTracks = cgiVarExists("hgt.reset");
     trackList = getTrackList(&groupList, defaultTracks ? -1 : -2);
     if (measureTiming)
 	measureTime("Time after visibilities");
     makeGlobalTrackHash(trackList);
     }
 }
 
 struct track *getTrackListForOneTrack(char *trackName)
 /* Fetch trackList for a single trackName using hgt.trackNameFilter. */
 {
 struct track *saveTrackList = trackList;
 struct group *saveGroupList = groupList;
@@ -8515,30 +8511,31 @@
 hPrintf(" ");
 
 hButtonWithOnClick("hgt.setWidth", "resize", "Resize image width to browser window size - keyboard shortcut: r, then s", "hgTracksSetWidth()");
 
 // put the track download interface behind hg.conf control
 if (cfgOptionBooleanDefault("showDownloadUi", FALSE))
     jsInline("var showDownloadButton = true;\n");
 }
 
 
 void doTrackForm(char *psOutput, struct tempName *ideoTn)
 /* Make the tracks display form with the zoom/scroll buttons and the active
  * image.  If the ideoTn parameter is not NULL, it is filled in if the
  * ideogram is created.  */
 {
+int disconCount = 0;
 struct group *group;
 struct track *track;
 char *freezeName = NULL;
 boolean hideAll = cgiVarExists("hgt.hideAll");
 boolean hideTracks = cgiOptionalString( "hideTracks") != NULL;
 boolean defaultTracks = cgiVarExists("hgt.reset");
 boolean showedRuler = FALSE;
 boolean showTrackControls = cartUsualBoolean(cart, "trackControlsOnMain", TRUE);
 boolean multiRegionButtonTop = cfgOptionBooleanDefault(MULTI_REGION_CFG_BUTTON_TOP, TRUE);
 long thisTime = 0, lastTime = 0;
 
 basesPerPixel = ((float)virtWinBaseCount) / ((float)fullInsideWidth);
 zoomedToBaseLevel = (virtWinBaseCount <= fullInsideWidth / tl.mWidth);
 zoomedToCodonLevel = (ceil(virtWinBaseCount/3) * tl.mWidth) <= fullInsideWidth;
 zoomedToCodonNumberLevel = (ceil(virtWinBaseCount/3) * tl.mWidth * 5) <= fullInsideWidth;
@@ -9467,84 +9464,86 @@
 	    if ((group->trackList == NULL) && (group->errMessage == NULL))
 		continue;
 
 	    struct trackRef *tr;
 
 	    /* check if group section should be displayed */
 	    char *otherState;
 	    char *indicator;
 	    char *indicatorImg;
 	    boolean isOpen = !isCollapsedGroup(group);
 	    collapseGroupGoodies(isOpen, TRUE, &indicatorImg,
 				    &indicator, &otherState);
 	    hPrintf("<TR>");
 	    cg->rowOpen = TRUE;
             if (group->errMessage)
-                hPrintf("<th align=\"left\" colspan=%d class='redToggleBar'>",MAX_CONTROL_COLUMNS);
+                hPrintf("<th align=\"left\" colspan=%d class='errorToggleBar'>",MAX_CONTROL_COLUMNS);
             else if (startsWith("Hub", group->label))
-                hPrintf("<th align=\"left\" colspan=%d class='mauveToggleBar'>",MAX_CONTROL_COLUMNS);
+                hPrintf("<th align=\"left\" colspan=%d class='hubToggleBar'>",MAX_CONTROL_COLUMNS);
             else if (startsWith("Quicklift", group->label))
-                hPrintf("<th align=\"left\" colspan=%d class='greenToggleBar'>",MAX_CONTROL_COLUMNS);
+                hPrintf("<th align=\"left\" colspan=%d class='quickToggleBar'>",MAX_CONTROL_COLUMNS);
             else
-                hPrintf("<th align=\"left\" colspan=%d class='blueToggleBar'>",MAX_CONTROL_COLUMNS);
+                hPrintf("<th align=\"left\" colspan=%d class='nativeToggleBar'>",MAX_CONTROL_COLUMNS);
             hPrintf("<table style='width:100%%;'><tr><td style='text-align:left;'>");
             hPrintf("\n<A NAME=\"%sGroup\"></A>",group->name);
 
 	    char idText[256];
 	    safef(idText, sizeof idText, "%s_button", group->name);
             hPrintf("<IMG class='toggleButton'"
                     " id='%s' src=\"%s\" alt=\"%s\" title='%s this group'>&nbsp;&nbsp;",
                     idText, indicatorImg, indicator,isOpen?"Collapse":"Expand");
 	    jsOnEventByIdF("click", idText, "return vis.toggleForGroup(this, '%s');", group->name);
 
             if (isHubTrack(group->name))
 		{
                 if (strstr(group->label, "Collections"))
                     {
                     safef(idText, sizeof idText, "%s_edit", group->name);
                     hPrintf("<input name=\"hubEditButton\" id='%s'"
                         " type=\"button\" value=\"edit\">\n", idText);
                     jsOnEventByIdF("click", idText,
                         "document.editHubForm.submit();return true;");
                     }
                 }
 
             hPrintf("</td><td style='text-align:center; width:90%%;'>\n<B>%s</B>", group->label);
             hPrintf("</td><td style='text-align:right;'>\n");
             if (isHubTrack(group->name))
 		{
-                struct trackHub *hub = grabHashedHub(group->name);
+                char *hubName = hubNameFromGroupName(group->name);
+                struct trackHub *hub = grabHashedHub(hubName);
 
                 // visibility: hidden means that the element takes up space so the center alignment is not disturbed.
                 if (hub != NULL)
                     {
                     if (hub->descriptionUrl == NULL)
                         hPrintf("<span title='The track hub authors have no provided a descriptionUrl with background "
                                 "information about this track hub' href='../goldenPath/help/hgTrackHubHelp.html#hub.txt' "
                                 "style='color:#FFF; font-size: 13px;' target=_blank>No Info</a>&nbsp;&nbsp;");
                     else
                         hPrintf("<a title='Documentation about this track hub, provided by the track hub authors (not UCSC)' href='%s' "
                             "style='color:#FFF; font-size: 13px;' target=_blank>Info</a>&nbsp;&nbsp;", hub->descriptionUrl);
                     }
 
-		safef(idText, sizeof idText, "%s_disconn", group->name);
+		safef(idText, sizeof idText, "%s_%d_disconn", hubName, disconCount);
+                disconCount++;
                 hPrintf("<input name=\"hubDisconnectButton\" id='%s'"
                     " type=\"button\" value=\"disconnect\">\n", idText);
 		jsOnEventByIdF("click", idText,
                     "document.disconnectHubForm.elements['hubId'].value='%s';"
                     "document.disconnectHubForm.submit();return true;",
-		    group->name + strlen(hubTrackPrefix));
+		    hubName + strlen(hubTrackPrefix));
 		}
 
             hPrintf("<input type='submit' name='hgt.refresh' value='refresh' "
                     "title='Update image with your changes'>\n");
             hPrintf("</td></tr></table></th>\n");
             controlGridEndRow(cg);
 
             /* Base Position track goes into map group, which will always exist. */
             if (!showedRuler && sameString(group->name, "map") )
 		{
 		char *url = trackUrl(RULER_TRACK_NAME, chromName);
 		showedRuler = TRUE;
 		myControlGridStartCell(cg, isOpen, group->name);
 		hPrintf("<A HREF=\"%s\">", url);
 		hPrintf(" %s<BR> ", RULER_TRACK_LABEL);