f80b3826a921197488ece1440ff08038ec9e572d
braney
  Mon Jun 29 12:28:07 2026 -0700
hgConvert/hgTracks: add option to hide target default tracks on QuickLift convert

Adds a "Hide all default tracks on the target" checkbox (on by default) to
the Convert page when QuickLift is enabled. When set, the QuickLift link
appends hideTracks=on, and hgTracks now leaves QuickLifted tracks visible
when hiding the target assembly's default tracks.

refs #37815

diff --git src/hg/hgTracks/hgTracks.c src/hg/hgTracks/hgTracks.c
index 6b526fc00bb..46377682eae 100644
--- src/hg/hgTracks/hgTracks.c
+++ src/hg/hgTracks/hgTracks.c
@@ -294,60 +294,64 @@
 
         if ((aNullPos != NULL) && (bNullPos != NULL) )
             *aNullPos = *bNullPos = '_';
 
         return ret;
         }
     else
         return -1;
     }
 else if (bIsHub)
     return 1;
 
 return iDif;
 }
 
-void changeTrackVisExclude(struct group *groupList, char *groupTarget, int changeVis, struct hash *excludeHash)
+void changeTrackVisExclude(struct group *groupList, char *groupTarget, int changeVis, struct hash *excludeHash, boolean keepQuickLift)
 /* Change track visibilities. If groupTarget is
  * NULL then set visibility for tracks in all groups.  Otherwise,
  * just set it for the given group.  If vis is -2, then visibility is
  * unchanged.  If -1 then set visibility to default, otherwise it should
  * be tvHide, tvDense, etc.
  * If we are going back to default visibility, then reset the track
  * ordering also.
  * If excludeHash is not NULL then don't change the visibility of the group names in that hash.
+ * If keepQuickLift is set then don't change the visibility of tracks lifted from another
+ * assembly via QuickLift.
  */
 {
 struct group *group;
 if (changeVis == -2)
     return;
 for (group = groupList; group != NULL; group = group->next)
     {
     struct trackRef *tr;
     if (excludeHash && hashLookup(excludeHash, group->name))
         continue;
 
     if (groupTarget == NULL || sameString(group->name,groupTarget))
         {
         static char pname[512];
         /* if default vis then reset group priority */
         if (changeVis == -1)
             group->priority = group->defaultPriority;
         for (tr = group->trackList; tr != NULL; tr = tr->next)
             {
             struct track *track = tr->track;
             struct trackDb *tdb = track->tdb;
+            if (keepQuickLift && (trackDbSetting(tdb, "quickLiftUrl") != NULL))
+                continue;   // leave QuickLifted tracks visible
             if (changeVis == -1) // to default
                 {
                 if (tdbIsComposite(tdb))
                     {
                     safef(pname, sizeof(pname),"%s.*",track->track); //to remove all settings associated with this composite!
                     cartRemoveLike(cart,pname);
                     struct track *subTrack;
                     for (subTrack = track->subtracks;subTrack != NULL; subTrack = subTrack->next)
                         {
                         subTrack->visibility = tdb->visibility;
                         cartRemove(cart, subTrack->track);
                         }
                     }
 
                 /* restore defaults */
@@ -428,31 +432,31 @@
             }
         }
     }
 slSort(&groupList, gCmpPriority);
 }
 
 void changeTrackVis(struct group *groupList, char *groupTarget, int changeVis)
 /* Change track visibilities. If groupTarget is
  * NULL then set visibility for tracks in all groups.  Otherwise,
  * just set it for the given group.  If vis is -2, then visibility is
  * unchanged.  If -1 then set visibility to default, otherwise it should
  * be tvHide, tvDense, etc.
  * If we are going back to default visibility, then reset the track
  * ordering also. */
 {
-changeTrackVisExclude(groupList, groupTarget, changeVis, NULL);
+changeTrackVisExclude(groupList, groupTarget, changeVis, NULL, FALSE);
 }
 
 int trackOffsetX()
 /* Return x offset where track display proper begins. */
 {
 int x = gfxBorder;
 if (withLeftLabels)
     x += tl.leftLabelWidth + gfxBorder;
 return x;
 }
 
 
 static void mapBoxTrackUi(struct hvGfx *hvg, int x, int y, int width,
                           int height, char *name, char *shortLabel, char *id)
 /* Print out image map rectangle that invokes hgTrackUi. */
@@ -7537,31 +7541,31 @@
 }
 loadCustomTracks(&trackList);
 makeDupeTracks(&trackList);
 groupTracks( &trackList, pGroupList, grpList, vis);
 setSearchedTrackToPackOrFull(trackList);
 char *rtsLoad = cgiOptionalString( "rtsLoad");
 if (rtsLoad)  // load a recommended track set using the merge method
     {
     // store session name and user
     char *otherUserName = cartOptionalString(cart, hgsOtherUserName);
     char *otherUserSessionName = rtsLoad;
 
     // Hide all tracks except custom tracks
     struct hash *excludeHash = newHash(2);
     hashStore(excludeHash, "user");
-    changeTrackVisExclude(groupList, NULL, tvHide, excludeHash);
+    changeTrackVisExclude(groupList, NULL, tvHide, excludeHash, FALSE);
 
     // delete any ordering we have
     char wildCard[32];
     safef(wildCard,sizeof(wildCard),"*_%s",IMG_ORDER_VAR);
     cartRemoveLike(cart, wildCard);
 
     if (loadRecTrackSetFromFile(cart, rtsLoad))
         {
         // Settings from the htdocs file are now overlaid on the cart.  The visibility
         // loop below and the draw path read them, so no redirect is needed.  Record
         // which set is loaded so hasRecTrackSet() and change detection still work, and
         // drop the one-shot action variable so it does not persist in the cart.
         cartSetString(cart, hgsOtherUserSessionName, rtsLoad);
         cartRemove(cart, "rtsLoad");
         }
@@ -7577,31 +7581,32 @@
             "&" hgsMergeCart "=on"
             "&" hgsDoOtherUser "=submit"
             "&hgsid=%s"
             , otherUserSessionName, otherUserName,cartSessionId(cart));
 
         cartCheckout(&cart);   // make sure cart records all our changes above
 
         // output the redirect and exit
         printf("<META HTTP-EQUIV=\"REFRESH\" CONTENT=\"0;URL=%s\">", newUrl);
         exit(0);
         }
     }
 
 boolean hideTracks = cgiOptionalString( "hideTracks") != NULL;
 if (hideTracks)
-    changeTrackVis(groupList, NULL, tvHide);    // set all top-level tracks to hide
+    // set all top-level tracks to hide, but leave QuickLifted tracks visible
+    changeTrackVisExclude(groupList, NULL, tvHide, NULL, TRUE);
 
 /* Get visibility values if any from ui. */
 struct hash *superTrackHash = newHash(5);  // cache whether supertrack is hiding tracks or not
 char buffer[4096];
 
 // Check to see if we have a versioned default gene track and let the knownGene 
 // cart variable determine its visibility
 char *defaultGeneTrack = NULL;
 char *knownDb = hdbDefaultKnownDb(database);
 if (differentString(knownDb, database))
     defaultGeneTrack = hdbGetMasterGeneTrack(knownDb);
 
 if (defaultGeneTrack)
     {
     char *s = cartOptionalString(cart, "knownGene");