ca95e568373e1398822741d9c4d4a162f167c7be
braney
  Fri Sep 4 13:24:21 2015 -0700
Another pass at #6551.   Put default visibilities in the cart at session
save.   On session load hide any tracks that are default visibile, but
aren't mentioned in the cart.

diff --git src/hg/hgSession/hgSession.c src/hg/hgSession/hgSession.c
index 645bc31..42d4f8a 100644
--- src/hg/hgSession/hgSession.c
+++ src/hg/hgSession/hgSession.c
@@ -588,30 +588,75 @@
 void cleanHgSessionFromCart(struct cart *cart)
 /* Remove hgSession action variables that should not stay in the cart. */
 {
 char varName[256];
 safef(varName, sizeof(varName), "%s%s", cgiBooleanShadowPrefix(), hgsSharePrefix);
 cartRemovePrefix(cart, varName);
 cartRemovePrefix(cart, hgsSharePrefix);
 cartRemovePrefix(cart, hgsLoadPrefix);
 cartRemovePrefix(cart, hgsLoadLocalFileName);
 cartRemovePrefix(cart, hgsDeletePrefix);
 cartRemovePrefix(cart, hgsDo);
 cartRemove(cart, hgsOldSessionName);
 cartRemove(cart, hgsCancel);
 }
 
+static void outIfNotPresent(struct cart *cart, struct dyString *dy, char *track, int tdbVis)
+/* Output default trackDb visibility if it's not mentioned in the cart. */
+{
+char *cartVis = cartOptionalString(cart, track);
+if (cartVis == NULL)
+    {
+    if (dy)
+        dyStringPrintf(dy,"&%s=%s", track, hStringFromTv(tdbVis));
+    else
+        printf("%s %s\n", track, hStringFromTv(tdbVis));
+    }
+}
+
+static void outDefaultTracks(struct cart *cart, struct dyString *dy)
+/* Output the default trackDb visibility for all tracks
+ * in trackDb if the track is not mentioned in the cart. */
+{
+char *database = cartString(cart, "db");
+struct trackDb *tdb = hTrackDb(database);
+struct hash *parentHash = newHash(5);
+
+for(; tdb; tdb = tdb->next)
+    {
+    struct trackDb *parent = tdb->parent;
+    if (parent) 
+        {
+        if (hashLookup(parentHash, parent->track) == NULL)
+            {
+            hashStore(parentHash, parent->track);
+            if (parent->isShow)
+                outIfNotPresent(cart, dy, parent->track, tvShow);
+            }
+        }
+    if (tdb->visibility != tvHide)
+        outIfNotPresent(cart, dy, tdb->track, tdb->visibility);
+    }
+
+// Put a variable in the cart that says we put the default 
+// visibilities in it.
+if (dy)
+    dyStringPrintf(dy,"&%s=on", CART_HAS_DEFAULT_VISIBILITY);
+else
+    printf("%s on", CART_HAS_DEFAULT_VISIBILITY);
+}
+
 #define INITIAL_USE_COUNT 0
 char *doNewSession()
 /* Save current settings in a new named session.
  * Return a message confirming what we did. */
 {
 struct dyString *dyMessage = dyStringNew(2048);
 char *sessionName = trimSpaces(cartString(cart, hgsNewSessionName));
 char *encSessionName = cgiEncodeFull(sessionName);
 boolean shareSession = cartBoolean(cart, hgsNewSessionShare);
 char *userName = getLinkUserName();
 char *encUserName = cgiEncodeFull(userName);
 struct sqlConnection *conn = hConnectCentral();
 
 if (sqlTableExists(conn, namedSessionTable))
     {
@@ -639,30 +684,34 @@
     dyStringClear(dy);
     sqlDyStringPrintf(dy, "DELETE FROM %s WHERE userName = '%s' AND "
 		       "sessionName = '%s';",
 		   namedSessionTable, encUserName, encSessionName);
     sqlUpdate(conn, dy->string);
 
     dyStringClear(dy);
     sqlDyStringPrintf(dy, "INSERT INTO %s ", namedSessionTable);
     dyStringAppend(dy, "(userName, sessionName, contents, shared, "
 		       "firstUse, lastUse, useCount) VALUES (");
     dyStringPrintf(dy, "'%s', '%s', ", encUserName, encSessionName);
     dyStringAppend(dy, "'");
     cleanHgSessionFromCart(cart);
     struct dyString *encoded = newDyString(4096);
     cartEncodeState(cart, encoded);
+
+    // Now add all the default visibilities to output.
+    outDefaultTracks(cart, encoded);
+
     sqlDyAppendEscaped(dy, encoded->string);
     dyStringFree(&encoded);
     dyStringAppend(dy, "', ");
     dyStringPrintf(dy, "%d, ", (shareSession ? 1 : 0));
     dyStringPrintf(dy, "%s, now(), %d);", firstUse, useCount);
     sqlUpdate(conn, dy->string);
     dyStringFree(&dy);
 
     /* Prevent modification of custom tracks just saved to namedSessionDb: */
     cartCopyCustomTracks(cart);
 
     if (useCount > INITIAL_USE_COUNT)
 	dyStringPrintf(dyMessage,
 	  "Overwrote the contents of session <B>%s</B> "
 	  "(that %s be shared with other users).  "
@@ -740,30 +789,31 @@
     hashFree(&sharedHash);
     }
 hel = cartFindPrefix(cart, hgsLoadPrefix);
 if (hel != NULL)
     {
     char *encSessionName = hel->name + strlen(hgsLoadPrefix);
     char *sessionName = cgiDecodeClone(encSessionName);
     char wildStr[256];
     safef(wildStr, sizeof(wildStr), "%s*", hgsLoadPrefix);
     dyStringPrintf(dyMessage,
 		   "Loaded settings from session <B>%s</B>. %s %s<BR>\n",
 		   htmlEncode(sessionName),
 		   getSessionLink(encUserName, encSessionName),
 		   getSessionEmailLink(encUserName, encSessionName));
     cartLoadUserSession(conn, userName, sessionName, cart, NULL, wildStr);
+    cartHideDefaultTracks(cart);
     hubConnectLoadHubs(cart);
     cartCopyCustomTracks(cart);
     cartCheckForCustomTracks(cart, dyMessage);
     didSomething = TRUE;
     }
 
 cartHelList = cartFindPrefix(cart, hgsDeletePrefix);
 for (hel = cartHelList;  hel != NULL;  hel = hel->next)
     {
     char *encSessionName = hel->name + strlen(hgsDeletePrefix);
     char *sessionName = cgiDecodeClone(encSessionName);
     sqlSafef(query, sizeof(query), "DELETE FROM %s "
 	  "WHERE userName = '%s' AND sessionName = '%s';",
 	  namedSessionTable, encUserName, encSessionName);
     sqlUpdate(conn, query);
@@ -788,48 +838,52 @@
  * Return a message confirming what we did. */
 {
 struct sqlConnection *conn = hConnectCentral();
 struct dyString *dyMessage = dyStringNew(1024);
 char *otherUser = trimSpaces(cartString(cart, hgsOtherUserName));
 char *sessionName = trimSpaces(cartString(cart, hgsOtherUserSessionName));
 char *encOtherUser = cgiEncodeFull(otherUser);
 char *encSessionName = cgiEncodeFull(sessionName);
 
 dyStringPrintf(dyMessage,
        "Loaded settings from user <B>%s</B>'s session <B>%s</B>. %s %s",
 	       otherUser, htmlEncode(sessionName),
 	       getSessionLink(otherUser, encSessionName),
 	       getSessionEmailLink(encOtherUser, encSessionName));
 cartLoadUserSession(conn, otherUser, sessionName, cart, NULL, actionVar);
+cartHideDefaultTracks(cart);
 hubConnectLoadHubs(cart);
 cartCopyCustomTracks(cart);
 cartCheckForCustomTracks(cart, dyMessage);
 hDisconnectCentral(&conn);
 return dyStringCannibalize(&dyMessage);
 }
 
 void doSaveLocal()
 /* Output current settings to be saved as a file on the user's machine.
  * Return a message confirming what we did. */
 {
 char *fileName = trimSpaces(cartString(cart, hgsSaveLocalFileName));
 char *compressType = cartString(cart, hgsSaveLocalFileCompress);
 struct pipeline *compressPipe = textOutInit(fileName, compressType, NULL);
 
 cleanHgSessionFromCart(cart);
 cartDump(cart);
 
+// Now add all the default visibilities to output.
+outDefaultTracks(cart, NULL);
+
 textOutClose(&compressPipe, NULL);
 }
 
 char *doLoad(boolean fromUrl, char *actionVar)
 /* Load settings from a file or URL sent by the user.
  * Return a message confirming what we did. */
 {
 struct dyString *dyMessage = dyStringNew(1024);
 struct lineFile *lf = NULL;
 webPushErrHandlersCartDb(cart, cartUsualString(cart, "db", NULL));
 if (fromUrl)
     {
     char *url = trimSpaces(cartString(cart, hgsLoadUrlName));
     if (isEmpty(url))
 	errAbort("Please go back and enter the URL (http://..., ftp://...) "
@@ -887,30 +941,31 @@
 		       "posted no data");
 	if (isNotEmpty(fileName))
 	    dyStringPrintf(dyMessage, ", only the filename <B>%s</B>",
 			   fileName);
 	dyStringAppend(dyMessage, ".  Your settings have not been changed.");
 	lf = NULL;
 	}
     dyStringPrintf(dyMessage, "&nbsp;&nbsp;"
 	   "<A HREF=\"http%s://%s%s?%s=%s\">Browser</A>",
 	   cgiAppendSForHttps(), cgiServerNamePort(), destAppScriptName(),
 	   cartSessionVarName(), cartSessionId(cart));
     }
 if (lf != NULL)
     {
     cartLoadSettings(lf, cart, NULL, actionVar);
+    cartHideDefaultTracks(cart);
     hubConnectLoadHubs(cart);
     cartCopyCustomTracks(cart);
     cartCheckForCustomTracks(cart, dyMessage);
     lineFileClose(&lf);
     }
 return dyStringCannibalize(&dyMessage);
 }
 
 char *doSessionDetail(char *sessionName)
 /* Show details about a particular session. */
 {
 struct dyString *dyMessage = dyStringNew(4096);
 char *encSessionName = cgiEncodeFull(sessionName);
 char *userName = getLinkUserName();
 char *encUserName = cgiEncodeFull(userName);