f621f87f73fd614e27adc747ba3ff044d2b4c4ad
braney
  Sat Jan 26 08:15:56 2019 -0800
Be smarter about setting track visibilities on the URL, including
dealing with super tracks, composites, and setting hub visibilities
without hub_ decoration.  Also, add ignoreCookies URL variable so folks
can link to a default cart.  #18544

diff --git src/hg/hgTracks/hgTracks.c src/hg/hgTracks/hgTracks.c
index 0e4ed87..3193f28 100644
--- src/hg/hgTracks/hgTracks.c
+++ src/hg/hgTracks/hgTracks.c
@@ -79,31 +79,31 @@
  * variables are not hgt. qualified.  It's a good idea if other
  * program's unique variables be qualified with a prefix though. */
 char *excludeVars[] = { "submit", "Submit", "dirty", "hgt.reset",
             "hgt.in1", "hgt.in2", "hgt.in3", "hgt.inBase",
             "hgt.out1", "hgt.out2", "hgt.out3", "hgt.out4",
             "hgt.left1", "hgt.left2", "hgt.left3",
             "hgt.right1", "hgt.right2", "hgt.right3",
             "hgt.dinkLL", "hgt.dinkLR", "hgt.dinkRL", "hgt.dinkRR",
             "hgt.tui", "hgt.hideAll", "hgt.visAllFromCt",
 	    "hgt.psOutput", "hideControls", "hgt.toggleRevCmplDisp",
 	    "hgt.collapseGroups", "hgt.expandGroups", "hgt.suggest",
 	    "hgt.jump", "hgt.refresh", "hgt.setWidth",
             "hgt.trackImgOnly", "hgt.ideogramToo", "hgt.trackNameFilter", "hgt.imageV1", "hgt.suggestTrack", "hgt.setWidth",
              TRACK_SEARCH,         TRACK_SEARCH_ADD_ROW,     TRACK_SEARCH_DEL_ROW, TRACK_SEARCH_PAGER,
             "hgt.contentType", "hgt.positionInput", "hgt.internal",
-            "sortExp", "sortSim",
+            "sortExp", "sortSim", "hideTracks",
             NULL };
 
 /* These variables persist from one incarnation of this program to the
  * next - living mostly in the cart. */
 boolean baseShowPos;           /* TRUE if should display full position at top of base track */
 boolean baseShowAsm;           /* TRUE if should display assembly info at top of base track */
 boolean baseShowScaleBar;      /* TRUE if should display scale bar at very top of base track */
 boolean baseShowRuler;         /* TRUE if should display the basic ruler in the base track (default) */
 char *baseTitle = NULL;        /* Title it should display top of base track (optional)*/
 static char *userSeqString = NULL;  /* User sequence .fa/.psl file. */
 
 /* These variables are set by getPositionFromCustomTracks() at the very
  * beginning of tracksDisplay(), and then used by loadCustomTracks(). */
 char *ctFileName = NULL;    /* Custom track file. */
 struct customTrack *ctList = NULL;  /* Custom tracks. */
@@ -6817,72 +6817,158 @@
     addWikiTrack(&trackList);
     struct sqlConnection *conn = wikiConnect();
     if (sqlTableExists(conn, "variome"))
         addVariomeWikiTrack(&trackList);
     wikiDisconnect(&conn);
     }
 
 struct grp *grpList = NULL;
 if (cartOptionalString(cart, "hgt.trackNameFilter") == NULL)
     { // If a single track was asked for and it is from a hub, then it is already in trackList
     loadTrackHubs(&trackList, &grpList);
     }
 loadCustomTracks(&trackList);
 groupTracks( &trackList, pGroupList, grpList, vis);
 setSearchedTrackToPackOrFull(trackList);
-if (cgiOptionalString( "hideTracks"))
-    changeTrackVis(groupList, NULL, tvHide);
+boolean hideTracks = cgiOptionalString( "hideTracks") != NULL;
+if (hideTracks)
+    changeTrackVis(groupList, NULL, tvHide);    // set all top-level tracks to hide
 
 /* Get visibility values if any from ui. */
+struct hash *superTrackHash = newHash(5);  // cache whether supertrack is hiding tracks or not
+
 for (track = trackList; track != NULL; track = track->next)
     {
-    char *s = cartOptionalString(cart, track->track);
-    if (startsWith("hub_", track->track) && (s == NULL))
-        s = cartOptionalString(cart, trackHubSkipHubName(track->track));
-    if (cgiOptionalString("hideTracks"))
-	{
+    // deal with any supertracks we're seeing for the first time
     if (tdbIsSuperTrackChild(track->tdb))
         {
-            s = cgiOptionalString(track->tdb->parent->track);
+        struct hashEl *hel = NULL;
+
+        if ((hel = hashLookup(superTrackHash, track->tdb->parent->track)) == NULL)   // we haven't seen this guy
+            {
+            // first deal with visibility of super track
+            char *s = hideTracks ? cgiOptionalString(track->tdb->parent->track) : cartOptionalString(cart, track->tdb->parent->track);
             if (s)
                 {
+                track->tdb->parent->visibility = hTvFromString(s) ;
                 cartSetString(cart, track->tdb->parent->track, s);
+                }
+            else if (startsWith("hub_", track->tdb->parent->track))
+                {
+                s = hideTracks ? cgiOptionalString( trackHubSkipHubName(track->tdb->parent->track)) :  cgiOptionalString( trackHubSkipHubName(track->tdb->parent->track));
+                if (s)
+                    {
+                    cartSetString(cart, track->tdb->parent->track, s);
+                    cartRemove(cart, trackHubSkipHubName(track->tdb->parent->track)); // remove the undecorated version
                     track->tdb->parent->visibility = hTvFromString(s) ;
                     }
                 }
-	s = cgiOptionalString(track->track);
+            
+            // now look to see if we have a _sel statement to turn off all subtracks (including the current one)
+            unsigned hideChildren = 0;
+            char buffer[4096];
+            char *usedThis = buffer;
+            safef(buffer, sizeof buffer, "%s_sel", track->tdb->parent->track);
+
+            s = cartOptionalString(cart, buffer);
+            if (s == NULL && startsWith("hub_", track->tdb->parent->track))
+                s = cartOptionalString(cart, usedThis = trackHubSkipHubName(buffer));
+
             if (s != NULL)
                 {
-	    if (hTvFromString(s) == track->tdb->visibility)
+                if (sameString(s, "0"))
+                    hideChildren = 1;
+                cartRemove(cart, usedThis);  // we don't want this hanging out in the cart
+                }
+
+            // mark this as having been addressed
+            hel = hashAddInt(superTrackHash, track->tdb->parent->track, hideChildren );  
+            }
+
+        if ( ptToInt(hel->val) == 1)    // we want to hide this track
+            {
+            if (tvHide == track->tdb->visibility)
+                /* remove if setting to default vis */
                 cartRemove(cart, track->track);
             else
+                cartSetString(cart, track->track, "hide");
+            track->visibility = tvHide;
+            }
+        }
+    
+    // we use cgiOptionString because the above code may have turned off the track in the cart if
+    // the user requested that all the default tracks be turned off
+    char *s = hideTracks ? cgiOptionalString(track->track) : cartOptionalString(cart, track->track);
+
+    if (s != NULL)
+        {
+        if (!track->limitedVisSet)
+            {
+            track->visibility = hTvFromString(s); 
             cartSetString(cart, track->track, s);
             }
         }
+    else
+        {
+        // maybe this track is on the URL without the hub_ prefix
+        if (startsWith("hub_", track->track))
+            s = cgiOptionalString(trackHubSkipHubName(track->track));
         if (s != NULL && !track->limitedVisSet)
+            {
             track->visibility = hTvFromString(s);
-    if (tdbIsCompositeChild(track->tdb))
-        track->visibility = tdbVisLimitedByAncestry(cart, track->tdb, FALSE);
-    else if (tdbIsComposite(track->tdb) && track->visibility != tvHide)
-	{
-	struct trackDb *parent = track->tdb->parent;
-	char *parentShow = NULL;
-	if (parent)
-	    parentShow = cartUsualString(cart, parent->track,
-			 parent->isShow ? "show" : "hide");
-	if (!parent || sameString(parentShow, "show"))
-	    compositeTrackVis(track);
+            cartSetString(cart, track->track, s);   // add the decorated visibility to the cart
+            cartRemove(cart, trackHubSkipHubName(track->track)); // remove the undecorated version
+            }
+        }
+
+    // now deal with composite track children
+    if (tdbIsComposite(track->tdb))
+        {
+        char buffer[4096];
+        char *usedThis = buffer;
+
+        // first check to see if we've been asked to hide all the subtracks
+        boolean hideTracks = FALSE;
+        safef(buffer, sizeof buffer, "%s_sel", track->track);
+
+        s = cartOptionalString(cart, buffer);
+        if (s == NULL && startsWith("hub_", track->track))
+            s = cartOptionalString(cart, usedThis = trackHubSkipHubName(buffer));
+        if ((s != NULL) && (sameString(s, "0")))
+            hideTracks = TRUE;
+        cartRemove(cart, usedThis);   // we don't want these _sel variables in the cart
+
+        // now see if we have any specified visibilities
+        struct track *subtrack;
+        for (subtrack = track->subtracks; subtrack != NULL; subtrack = subtrack->next)
+            {
+            char *s = cartOptionalString(cart, subtrack->track);
+            if (s == NULL && startsWith("hub_", subtrack->track))
+                s = cartOptionalString(cart, trackHubSkipHubName(subtrack->track));
+
+            char buffer[4096];
+            safef(buffer, sizeof buffer, "%s_sel", subtrack->track);
+            if (s != NULL)
+                {
+                if (sameString("hide", s))
+                    cartSetString(cart, buffer, "0");
+                else
+                    cartSetString(cart, buffer, "1");
+                }
+            else if (hideTracks && isSubtrackVisible(subtrack))
+                cartSetString(cart, buffer, "0");
+            }
         }
     }
 return trackList;
 }
 
 char *collapseGroupVar(char *name)
 /* Construct cart variable name for collapsing group */
 {
 static char varName[256];
 safef(varName, sizeof(varName),
         "%s%s_%s_%s", "hgt", "group", name, "close");
 return (cloneString(varName));
 }
 
 boolean isCollapsedGroup(struct group *grp)