1bda3889beb9b9247998d9153dee94ca7d13810c braney Sun Nov 10 16:16:48 2019 -0800 allow yet another way to specify bigBed filters. This allows specifications of the form "filter*.fieldName" diff --git src/hg/lib/hui.c src/hg/lib/hui.c index 3891014..1679f97 100644 --- src/hg/lib/hui.c +++ src/hg/lib/hui.c @@ -3621,121 +3621,130 @@ if (val == filterBy->slValues) // First one filterBy->valueAndLabel = TRUE; if (filterBy->valueAndLabel == FALSE) errAbort("filterBy values either all have labels (as value|label) " "or none do."); *chipper++ = 0; // The label is found inside filters->svValues as the next string strSwapChar(chipper,'_',' '); // Title does not have underscores } else if (filterBy->valueAndLabel) errAbort("filterBy values either all have labels in form of value|label " "or none do."); } } } -char *extractFieldName(char *cartVariable, char *filterType) -/* Extract field name from a filter cart variable. Variables can either be +char *extractFieldNameNew(char *trackDbVariable, char *filterType) +/* Extract field name from a filter trackDb variable. Variables are filter*.column */ +{ +char *ptr = strchr(trackDbVariable, '.'); +if (ptr == NULL) + errAbort("%s doesn't have a '.' in it", trackDbVariable); + +return ptr + 1; +} + +char *extractFieldNameOld(char *trackDbVariable, char *filterType) +/* Extract field name from a filter trackDb variable. Variables can either be * <columnName>Filter* or <columnName>.Filter* */ { -char *field = cloneString(cartVariable); +char *field = cloneString(trackDbVariable); int ix = strlen(field) - strlen(filterType); field[ix] = '\0'; if (field[ix - 1] == '.') field[ix - 1] = '\0'; return field; } static char *getLabelSetting(struct cart *cart, struct trackDb *tdb, char *field) { char labelSetting[4096]; safef(labelSetting, sizeof labelSetting, "%s%s", field, FILTER_LABEL_NAME); char *trackDbLabel = cartOrTdbString(cart, tdb, labelSetting, NULL); if (trackDbLabel == NULL) { safef(labelSetting, sizeof labelSetting, "%s.%s", field, FILTER_LABEL_NAME); trackDbLabel = cartOrTdbString(cart, tdb, labelSetting, NULL); } return trackDbLabel; } -filterBy_t *buildFilterBy(struct trackDb *tdb, struct cart *cart, struct asObject *as, char *filterName, char *name) +static filterBy_t *buildFilterBy(struct trackDb *tdb, struct cart *cart, struct asObject *as, struct trackDbFilter *tdbFilter, char *name) /* Build a filterBy_t structure from a <column>FilterValues statement. */ { -char *field = extractFieldName(filterName, FILTER_VALUES_NAME); -char *setting = trackDbSetting(tdb, filterName); -if (isEmpty(setting)) - errAbort("FilterValues setting of field '%s' must have a value.", field); +char *field = tdbFilter->fieldName; +if (isEmpty(tdbFilter->setting)) + errAbort("FilterValues setting of field '%s' must have a value.", tdbFilter->fieldName); -char *value = cartUsualStringClosestToHome(cart, tdb, FALSE, filterName, setting); +char *value = cartUsualStringClosestToHome(cart, tdb, FALSE, tdbFilter->name, tdbFilter->setting); filterBy_t *filterBy; AllocVar(filterBy); -filterBy->column = field; -filterBy->title = field; /// title should come from AS file, or trackDb variable +filterBy->column = cloneString(field); +filterBy->title = cloneString(field); /// title should come from AS file, or trackDb variable struct asColumn *asCol = asColumnFind(as, field); if (asCol != NULL) filterBy->title = asCol->comment; else errAbort("Building filter on field %s which is not in AS file.", field); char *trackDbLabel = getLabelSetting(cart, tdb, field); if (trackDbLabel) filterBy->title = trackDbLabel; filterBy->useIndex = FALSE; filterBy->slValues = slNameListFromCommaEscaped(value); chopUpValues(filterBy); if (cart != NULL) { char suffix[256]; safef(suffix, sizeof(suffix), "%s.%s", "filterBy", filterBy->column); boolean parentLevel = isNameAtParentLevel(tdb,tdb->track); if (cartLookUpVariableClosestToHome(cart,tdb,parentLevel,suffix,&(filterBy->htmlName))) { filterBy->slChoices = cartOptionalSlNameList(cart,filterBy->htmlName); freeMem(filterBy->htmlName); } } struct dyString *dy = newDyString(128); dyStringPrintf(dy, "%s.%s.%s", name, "filterBy", filterBy->column); filterBy->htmlName = dy->string; return filterBy; } -filterBy_t *filterByValues(struct trackDb *tdb, struct cart *cart, struct slName *filterValues, char *name) +filterBy_t *filterByValues(struct trackDb *tdb, struct cart *cart, struct trackDbFilter *trackDbFilters, char *name) /* Build a filterBy_t list from tdb variables of the form *FilterValues */ { struct asObject *as = asForTdb(NULL, tdb); filterBy_t *filterByList = NULL, *filter; -struct slName *fieldFilter; -while ((fieldFilter = slPopHead(&filterValues)) != NULL) +struct trackDbFilter *fieldFilter; +while ((fieldFilter = slPopHead(&trackDbFilters)) != NULL) { - if ((filter = buildFilterBy(tdb, cart, as, fieldFilter->name, name)) != NULL) + if ((filter = buildFilterBy(tdb, cart, as, fieldFilter, name)) != NULL) slAddHead(&filterByList, filter); } return filterByList; } filterBy_t *filterBySetGetGuts(struct trackDb *tdb, struct cart *cart, char *name, char *subName, char *settingName) // Gets one or more "filterBy" settings (ClosestToHome). returns NULL if not found { // first check to see if this tdb is using "new" FilterValues cart variables -struct slName *filterValues = trackDbSettingsWildMatch(tdb, FILTER_VALUES_WILDCARD); -if (filterValues) - return filterByValues(tdb, cart, filterValues, name); +struct trackDbFilter *trackDbFilters = tdbGetTrackFilterByFilters( tdb); +if (trackDbFilters) + return filterByValues(tdb, cart, trackDbFilters, name); filterBy_t *filterBySet = NULL; char *setting = trackDbSettingClosestToHome(tdb, settingName); if(setting == NULL) return NULL; if ( name == NULL ) name = tdb->track; setting = cloneString(setting); char *filters[10]; // multiple filterBys are delimited by space but spaces inside filter can be protected "by quotes" int filterCount = chopByWhiteRespectDoubleQuotes(setting, filters, ArraySize(filters)); int ix; for (ix=0;ix<filterCount;ix++) { @@ -3957,38 +3966,31 @@ { char *styler = label + strlen(label)+1; if (*styler != '\0') { if (*styler == '#') // Legacy: just the color that follows printf(" style='color: %s;'",styler); else printf(" style='%s'",styler); } } printf(">%s</OPTION>\n",label); } static boolean filterByColumnIsMultiple(struct cart *cart, struct trackDb *tdb, char *column) { -char settingString[4096]; -safef(settingString, sizeof settingString, "%s%s", column, FILTER_TYPE_NAME); -char *setting = cartOrTdbString(cart, tdb, settingString, NULL); -if (setting == NULL) - { - safef(settingString, sizeof settingString, "%s.%s", column, FILTER_TYPE_NAME); - setting = cartOrTdbString(cart, tdb, settingString, FILTERBY_MULTIPLE_LIST_AND); - } +char *setting = getFilterType(cart, tdb, column, FILTERBY_MULTIPLE_LIST_AND); return (sameString(setting, FILTERBY_MULTIPLE) || sameString(setting, FILTERBY_MULTIPLE_LIST_OR) || sameString(setting, FILTERBY_MULTIPLE_LIST_AND)); } void filterBySetCfgUiGuts(struct cart *cart, struct trackDb *tdb, filterBy_t *filterBySet, boolean onOneLine, char *filterTypeTitle, char *selectIdPrefix, char *allLabel, char *prefix) // Does the UI for a list of filterBy structure for either filterBy or highlightBy controls { if (filterBySet == NULL) return; #define FILTERBY_HELP_LINK "<A HREF=\"../goldenPath/help/multiView.html\" TARGET=ucscHelp>help</A>" int count = slCount(filterBySet); @@ -4027,35 +4029,33 @@ safef(selectStatement, sizeof selectStatement, " (select multiple items - %s)", FILTERBY_HELP_LINK); else selectStatement[0] = 0; if(count == 1) printf("<B>%s by %s</B>%s",filterTypeTitle,filterBy->title,selectStatement); else printf("<B>%s</B>",filterBy->title); puts("</TD>"); } puts("</tr><tr>"); for (filterBy = filterBySet; filterBy != NULL; filterBy = filterBy->next) { puts("<td>"); if (filterByColumnIsMultiple(cart, tdb, filterBy->column) && tdbIsBigBed(tdb)) { - char settingString[4096]; - safef(settingString, sizeof settingString, "%s%s", filterBy->column, FILTER_TYPE_NAME); - char *setting = cartOrTdbString(cart, tdb, settingString, FILTERBY_MULTIPLE_LIST_AND); + char *setting = getFilterType(cart, tdb, filterBy->column, FILTERBY_MULTIPLE_LIST_AND); char cartSettingString[4096]; - safef(cartSettingString, sizeof cartSettingString, "%s.%s", prefix, settingString); + safef(cartSettingString, sizeof cartSettingString, "%s.%s.%s", prefix, filterBy->column, FILTER_TYPE_NAME_CAP); printf("<div class='advanced' style='display:none'><b>Match if "); cgiMakeRadioButton(cartSettingString, FILTERBY_MULTIPLE_LIST_AND, sameString(setting, FILTERBY_MULTIPLE_LIST_AND)); printf(" all "); cgiMakeRadioButton(cartSettingString, FILTERBY_MULTIPLE_LIST_OR, sameString(setting, FILTERBY_MULTIPLE_LIST_OR)); printf(" one or more match</b></div> "); } puts("</td>"); } puts("</tr><tr>"); int ix=0; for (filterBy = filterBySet; filterBy != NULL; filterBy = filterBy->next, ix++) { puts("<td>"); // value is always "All", even if label is different, to simplify javascript code int valIx = 0; @@ -5832,58 +5832,74 @@ *min = NULL; // default these outs! if (max) *max = NULL; char *setting = trackDbSettingClosestToHome(tdb, scoreName); if (setting) { if (strchr(setting,':') != NULL) return colonPairToStrings(setting,min,max); else if (min) *min = cloneString(setting); return TRUE; } return FALSE; } +char *getScoreNameAdd(struct trackDb *tdb, char *scoreName, char *add) +// Add a suffix to a filter for more information +{ +char scoreLimitName[1024]; +char *name = cloneString(scoreName); +if (tdb->isNewFilterType) + { + char *dot = strchr(name, '.'); + *dot++ = 0; + safef(scoreLimitName, sizeof(scoreLimitName), "%s%s.%s", name, add, dot); + } +else + safef(scoreLimitName, sizeof(scoreLimitName), "%s%s", scoreName, add); +return cloneString(scoreLimitName); +} + static boolean getScoreLimitsFromTdb(struct trackDb *tdb, char *scoreName,char *defaults, char**min,char**max) // returns TRUE if limits exist and sets the string pointer (because they may be float or int) // if min or max are set, then they should be freed { if (min) *min = NULL; // default these outs! if (max) *max = NULL; -char scoreLimitName[128]; -safef(scoreLimitName, sizeof(scoreLimitName), "%s%s", scoreName, _LIMITS); + +char *scoreLimitName = getScoreNameAdd(tdb, scoreName, _LIMITS); char *setting = trackDbSettingClosestToHome(tdb, scoreLimitName); if (setting) { return colonPairToStrings(setting,min,max); } else { if (min) { - safef(scoreLimitName, sizeof(scoreLimitName), "%s%s", scoreName, _MIN); + scoreLimitName = getScoreNameAdd(tdb, scoreName, _MIN); setting = trackDbSettingClosestToHome(tdb, scoreLimitName); if (setting) *min = cloneString(setting); } if (max) { - safef(scoreLimitName, sizeof(scoreLimitName), "%s%s", scoreName, _MAX); + scoreLimitName = getScoreNameAdd(tdb, scoreName, _MAX); setting = trackDbSettingClosestToHome(tdb, scoreLimitName); if (setting) *max = cloneString(setting); } return TRUE; } if (defaults != NULL && ((min && *min == NULL) || (max && *max == NULL))) { char *minLoc=NULL; char *maxLoc=NULL; if (colonPairToStrings(defaults,&minLoc,&maxLoc)) { if (min && *min == NULL && minLoc != NULL) *min=minLoc; else @@ -5944,60 +5960,60 @@ && *limitMin != NO_VALUE && (*min == NO_VALUE || *min < *limitMin)) *min = *limitMin; if (min && limitMax && *limitMax != NO_VALUE && *min > *limitMax) *min = *limitMax; if (max && limitMax && *limitMax != NO_VALUE && (*max == NO_VALUE || *max > *limitMax)) *max = *limitMax; if (max && limitMin && *limitMin != NO_VALUE && *max < *limitMin) *max = *limitMin; } void getScoreFloatRangeFromCart(struct cart *cart, struct trackDb *tdb, boolean parentLevel, char *scoreName, double *limitMin,double *limitMax,double*min,double*max) // gets an double score range from the cart, but the limits from trackDb // for any of the pointers provided, will return a value found, if found, else it's contents // are undisturbed (use NO_VALUE to recognize unavaliable values) { -char scoreLimitName[128]; char *deMin=NULL,*deMax=NULL; if ((limitMin || limitMax) && getScoreLimitsFromTdb(tdb,scoreName,NULL,&deMin,&deMax)) { if (deMin != NULL && limitMin) *limitMin = strtod(deMin,NULL); if (deMax != NULL && limitMax) *limitMax =strtod(deMax,NULL); freeMem(deMin); freeMem(deMax); } if ((min || max) && getScoreDefaultsFromTdb(tdb,scoreName,NULL,&deMin,&deMax)) { if (deMin != NULL && min) *min = strtod(deMin,NULL); if (deMax != NULL && max) *max =strtod(deMax,NULL); freeMem(deMin); freeMem(deMax); } if (max) { - safef(scoreLimitName, sizeof(scoreLimitName), "%s%s", scoreName, _MAX); + char *scoreLimitName = getScoreNameAdd(tdb, scoreName, _MAX); + deMax = cartOptionalStringClosestToHome(cart, tdb,parentLevel,scoreLimitName); if (deMax != NULL) *max = strtod(deMax,NULL); } if (min) { // name is always {filterName}Min - safef(scoreLimitName, sizeof(scoreLimitName), "%s%s", scoreName, _MIN); + char *scoreLimitName = getScoreNameAdd(tdb, scoreName, _MIN); deMin = cartOptionalStringClosestToHome(cart, tdb,parentLevel,scoreLimitName); if (deMin == NULL) deMin = cartOptionalStringClosestToHome(cart, tdb,parentLevel,scoreName); if (deMin != NULL) *min = strtod(deMin,NULL); } // Defaulting min and max within limits. Sorry for the horizontal ifs, // but stacking the group makes them easier to follow if (min && limitMin && (int)(*limitMin) != NO_VALUE && ((int)(*min) == NO_VALUE || *min < *limitMin)) *min = *limitMin; if (min && limitMax && (int)(*limitMax) != NO_VALUE && *min > *limitMax) *min = *limitMax; if (max && limitMax && (int)(*limitMax) != NO_VALUE && ((int)(*max) == NO_VALUE || *max > *limitMax)) *max = *limitMax; if (max && limitMin @@ -6009,198 +6025,269 @@ char *label, char *scoreName) // Shows a score filter control with minimum value and optional range { char *setting = trackDbSetting(tdb, scoreName); if (setting) { if (*opened == FALSE) { boxed = cfgBeginBoxAndTitle(tdb, boxed, title); puts("<TABLE>"); *opened = TRUE; } printf("<TR><TD align='right'><B>%s:</B><TD align='left'>",label); char varName[256]; char altLabel[256]; - safef(varName, sizeof(varName), "%s%s", scoreName, _BY_RANGE); - boolean filterByRange = trackDbSettingClosestToHomeOn(tdb, varName); + char *filterName = getScoreNameAdd(tdb, scoreName, _BY_RANGE); + boolean filterByRange = trackDbSettingClosestToHomeOn(tdb, filterName); double minLimit=NO_VALUE,maxLimit=NO_VALUE; double minVal=minLimit,maxVal=maxLimit; colonPairToDoubles(setting,&minVal,&maxVal); getScoreFloatRangeFromCart(cart,tdb,parentLevel,scoreName,&minLimit,&maxLimit, &minVal, &maxVal); - safef(varName, sizeof(varName), "%s.%s%s", name, scoreName, filterByRange ? _MIN:""); + filterName = getScoreNameAdd(tdb, scoreName, filterByRange ? _MIN:""); + safef(varName, sizeof(varName), "%s.%s", name, filterName); safef(altLabel, sizeof(altLabel), "%s%s", (filterByRange ? "Minimum " : ""), htmlEncode(htmlTextStripTags(label))); cgiMakeDoubleVarWithLimits(varName,minVal, altLabel, 0,minLimit, maxLimit); if (filterByRange) { printf("<TD align='left'>to<TD align='left'>"); - safef(varName, sizeof(varName), "%s.%s%s", name, scoreName, _MAX); + filterName = getScoreNameAdd(tdb, scoreName, _MAX); + safef(varName, sizeof(varName), "%s.%s", name, filterName); safef(altLabel, sizeof(altLabel), "%s%s", (filterByRange?"Maximum ":""), label); cgiMakeDoubleVarWithLimits(varName,maxVal, altLabel, 0,minLimit, maxLimit); } safef(altLabel, sizeof(altLabel), "%s", (filterByRange?"": "colspan=3")); if (minLimit != NO_VALUE && maxLimit != NO_VALUE) printf("<TD align='left'%s> (%g to %g)",altLabel,minLimit, maxLimit); else if (minLimit != NO_VALUE) printf("<TD align='left'%s> (minimum %g)",altLabel,minLimit); else if (maxLimit != NO_VALUE) printf("<TD align='left'%s> (maximum %g)",altLabel,maxLimit); else printf("<TD align='left'%s",altLabel); puts("</TR>"); return TRUE; } return FALSE; } +struct trackDbFilter *tdbGetTrackFilters( struct trackDb *tdb, char * lowWild, char * lowName, char * capWild, char * capName) +// figure out which of the ways to specify trackDb filter variables we're using +// and return the setting +{ +struct trackDbFilter *trackDbFilterList = NULL; +struct slName *filterSettings = trackDbSettingsWildMatch(tdb, lowWild); + +if (filterSettings) + { + struct trackDbFilter *tdbFilter; + struct slName *filter = NULL; + while ((filter = slPopHead(&filterSettings)) != NULL) + { + tdb->isNewFilterType = TRUE; + + AllocVar(tdbFilter); + slAddHead(&trackDbFilterList, tdbFilter); + tdbFilter->name = cloneString(filter->name); + tdbFilter->setting = trackDbSetting(tdb, filter->name); + tdbFilter->fieldName = extractFieldNameNew(filter->name, lowName); + } + } +filterSettings = trackDbSettingsWildMatch(tdb, capWild); + +if (filterSettings) + { + struct trackDbFilter *tdbFilter; + struct slName *filter = NULL; + while ((filter = slPopHead(&filterSettings)) != NULL) + { + if (differentString(filter->name,NO_SCORE_FILTER)) + { + if (tdb->isNewFilterType) + errAbort("browser doesn't support specifying filters in both old and new format."); + AllocVar(tdbFilter); + slAddHead(&trackDbFilterList, tdbFilter); + tdbFilter->name = cloneString(filter->name); + tdbFilter->setting = trackDbSetting(tdb, filter->name); + tdbFilter->fieldName = extractFieldNameOld(filter->name, capName); + } + } + } + +return trackDbFilterList; +} + +struct trackDbFilter *tdbGetTrackNumFilters( struct trackDb *tdb) +// get the number filters out of trackDb +{ +return tdbGetTrackFilters( tdb, FILTER_NUMBER_WILDCARD_LOW, FILTER_NUMBER_NAME_LOW, FILTER_NUMBER_WILDCARD_CAP, FILTER_NUMBER_NAME_CAP); +} + +struct trackDbFilter *tdbGetTrackTextFilters( struct trackDb *tdb) +// get the text filters out of trackDb +{ +return tdbGetTrackFilters( tdb, FILTER_TEXT_WILDCARD_LOW, FILTER_TEXT_NAME_LOW, FILTER_TEXT_WILDCARD_CAP, FILTER_TEXT_NAME_CAP); +} + +struct trackDbFilter *tdbGetTrackFilterByFilters( struct trackDb *tdb) +// get the values filters out of trackDb +{ +return tdbGetTrackFilters( tdb, FILTER_VALUES_WILDCARD_LOW, FILTER_VALUES_NAME_LOW, FILTER_VALUES_WILDCARD_CAP, FILTER_VALUES_NAME_CAP); +} static int numericFiltersShowAll(char *db, struct cart *cart, struct trackDb *tdb, boolean *opened, boolean boxed, boolean parentLevel,char *name, char *title) // Shows all *Filter style filters. Note that these are in random order and have no graceful title { int count = 0; -struct slName *filterSettings = trackDbSettingsWildMatch(tdb, FILTER_NUMBER_WILDCARD); -if (filterSettings) +struct trackDbFilter *trackDbFilters = tdbGetTrackNumFilters(tdb); +if (trackDbFilters) { puts("<BR>"); - struct slName *filter = NULL; + struct trackDbFilter *filter = NULL; struct sqlConnection *conn = NULL; if (!isHubTrack(db)) conn = hAllocConnTrack(db, tdb); struct asObject *as = asForTdb(conn, tdb); hFreeConn(&conn); - while ((filter = slPopHead(&filterSettings)) != NULL) - { - if (differentString(filter->name,NO_SCORE_FILTER)) + while ((filter = slPopHead(&trackDbFilters)) != NULL) { + char *field = filter->fieldName; char *scoreName = cloneString(filter->name); - char *field = extractFieldName(filter->name, FILTER_NUMBER_NAME); char *trackDbLabel = getLabelSetting(cart, tdb, field); if (as != NULL) { struct asColumn *asCol = asColumnFind(as, field); if (asCol != NULL) { // Found label so replace field field = asCol->comment; } else errAbort("Building filter on field %s which is not in AS file.", field); } - char varName[256]; char labelBuf[1024]; char *label = labelBuf; - safef(varName, sizeof(varName), "%s%s", scoreName, _BY_RANGE); - boolean filterByRange = trackDbSettingClosestToHomeOn(tdb, varName); + char *filterName = getScoreNameAdd(tdb, scoreName, _BY_RANGE); + boolean filterByRange = trackDbSettingClosestToHomeOn(tdb, filterName); if (trackDbLabel) label = trackDbLabel; else safef(labelBuf, sizeof(labelBuf),"%s%s", filterByRange ? "": "Minimum ", field); showScoreFilter(cart,tdb,opened,boxed,parentLevel,name,title,label,scoreName); - freeMem(scoreName); count++; } - slNameFree(&filter); - } if (as != NULL) asObjectFree(&as); } if (count > 0) puts("</TABLE>"); return count; } boolean bedScoreHasCfgUi(struct trackDb *tdb) // Confirms that this track has a bedScore Cfg UI { // Assumes that cfgType == cfgBedScore if (trackDbSettingClosestToHome(tdb, FILTER_BY)) return TRUE; if (trackDbSettingClosestToHome(tdb, GRAY_LEVEL_SCORE_MIN)) return TRUE; boolean blocked = FALSE; -struct slName *filterSettings = trackDbSettingsWildMatch(tdb, FILTER_NUMBER_WILDCARD); +struct trackDbFilter *filterSettings = tdbGetTrackNumFilters( tdb); + if (filterSettings != NULL) { boolean one = FALSE; - struct slName *oneFilter = filterSettings; + struct trackDbFilter *oneFilter = filterSettings; + char *noScoreFilter = trackDbSetting(tdb, NO_SCORE_FILTER); + if (noScoreFilter) + blocked = TRUE; + for (;oneFilter != NULL;oneFilter=oneFilter->next) { - if (sameWord(NO_SCORE_FILTER,oneFilter->name)) - { - blocked = TRUE; - continue; - } - if (differentString(oneFilter->name,SCORE_FILTER)) // scoreFilter is implicit + if (differentString(oneFilter->fieldName,"score")) // scoreFilter is implicit { // but could be blocked one = TRUE; break; } } - slNameFreeList(&filterSettings); if (one) return TRUE; } if (!blocked) // scoreFilter is implicit unless NO_SCORE_FILTER return TRUE; return FALSE; } +char *getFilterType(struct cart *cart, struct trackDb *tdb, char *field, char *def) +// figure out how the trackDb is specifying the FILTER_TYPE variable and return its setting +{ +char settingString[4096]; +safef(settingString, sizeof settingString, "%s.%s", FILTER_TYPE_NAME_LOW, field); +char *setting = cartOrTdbString(cart, tdb, settingString, NULL); +if (setting == NULL) + { + safef(settingString, sizeof settingString, "%s%s", field, FILTER_TYPE_NAME_CAP); + setting = cartOrTdbString(cart, tdb, settingString, NULL); + } +if (setting == NULL) + { + safef(settingString, sizeof settingString, "%s.%s", field, FILTER_TYPE_NAME_CAP); + setting = cartOrTdbString(cart, tdb, settingString, def); + } +return setting; +} + static int textFiltersShowAll(char *db, struct cart *cart, struct trackDb *tdb) /* Show all the text filters for this track. */ { int count = 0; -struct slName *filter, *filterSettings = trackDbSettingsWildMatch(tdb, FILTER_TEXT_WILDCARD); -if (filterSettings) +struct trackDbFilter *trackDbFilters = tdbGetTrackTextFilters(tdb); +if (trackDbFilters) { + puts("<BR>"); + struct trackDbFilter *filter = NULL; struct sqlConnection *conn = NULL; if (!isHubTrack(db)) conn = hAllocConnTrack(db, tdb); - while ((filter = slPopHead(&filterSettings)) != NULL) - { - char *setting = trackDbSetting(tdb, filter->name); - char *value = cartUsualStringClosestToHome(cart, tdb, FALSE, filter->name, setting); - char *field = extractFieldName(filter->name, FILTER_TEXT_NAME); struct asObject *as = asForTdb(conn, tdb); - struct asColumn *asCol = asColumnFind(as, field); + hFreeConn(&conn); + while ((filter = slPopHead(&trackDbFilters)) != NULL) + { + char *value = cartUsualStringClosestToHome(cart, tdb, FALSE, filter->name, filter->setting); + struct asColumn *asCol = asColumnFind(as, filter->fieldName); if (asCol == NULL) - errAbort("Building filter on field %s which is not in AS file.", field); + errAbort("Building filter on field %s which is not in AS file.", filter->fieldName); count++; - printf("<P><B>Filter items in '%s' field: ", field); + printf("<P><B>Filter items in '%s' field: ", filter->fieldName); char cgiVar[128]; safef(cgiVar,sizeof(cgiVar),"%s.%s",tdb->track,filter->name); cgiMakeTextVar(cgiVar, value, 45); - char settingString[4096]; - safef(settingString, sizeof settingString, "%s%s", field, FILTER_TYPE_NAME); - setting = cartOrTdbString(cart, tdb, settingString, NULL); - if (setting == NULL) - { - safef(settingString, sizeof settingString, "%s.%s", field, FILTER_TYPE_NAME); - setting = cartOrTdbString(cart, tdb, settingString, FILTERTEXT_WILDCARD); - } - safef(cgiVar,sizeof(cgiVar),"%s.%s",tdb->track,settingString); + char *setting = getFilterType(cart, tdb, filter->fieldName, FILTERTEXT_WILDCARD); + safef(cgiVar,sizeof(cgiVar),"%s.%s.%s",tdb->track,filter->fieldName, FILTER_TYPE_NAME_CAP); printf(" using "); printf("<SELECT name='%s'> ", cgiVar); printf("<OPTION %s>%s</OPTION>", sameString(setting, FILTERTEXT_WILDCARD) ? "SELECTED" : "", FILTERTEXT_WILDCARD ); printf("<OPTION %s>%s</OPTION>", sameString(setting, FILTERTEXT_REGEXP) ? "SELECTED" : "", FILTERTEXT_REGEXP ); printf("</SELECT>"); printf("</P>"); } } return count; } void scoreCfgUi(char *db, struct cart *cart, struct trackDb *tdb, char *name, char *title, int maxScore, boolean boxed) // Put up UI for filtering bed track based on a score @@ -6667,31 +6754,31 @@ // warn("SELECT FROM %s WHERE %s",tdb->table,dyStringContents(extraWhere)); return extraWhere; } struct dyString *dyAddAllScoreFilters(struct cart *cart, struct trackDb *tdb, struct dyString *extraWhere,boolean *and) // creates the where clause condition to gather together all random double filters // Filters are expected to follow // {fiterName}: trackDb min or min:max - default value(s); // {filterName}Min or {filterName}: min (user supplied) cart variable; // {filterName}Max: max (user supplied) cart variable; // {filterName}Limits: trackDb allowed range "0.0:10.0" Optional // uses: defaultLimits: function param if no tdb limits settings found) // The 'and' param and dyString in/out allows stringing multiple where clauses together { -struct slName *filterSettings = trackDbSettingsWildMatch(tdb, FILTER_NUMBER_WILDCARD); +struct slName *filterSettings = trackDbSettingsWildMatch(tdb, FILTER_NUMBER_WILDCARD_CAP); if (filterSettings) { struct slName *filter = NULL; while ((filter = slPopHead(&filterSettings)) != NULL) { if (differentString(filter->name,"noScoreFilter") && differentString(filter->name,"scoreFilter")) // TODO: scoreFilter could be included { char *field = cloneString(filter->name); int ix = strlen(field) - strlen("filter"); assert(ix > 0); field[ix] = '\0'; char *setting = trackDbSetting(tdb, filter->name); // How to determine float or int ? // If actual tracDb setting has decimal places, then float!