diff options
Diffstat (limited to 'app/bin/paramfilesearch_ui.c')
-rw-r--r-- | app/bin/paramfilesearch_ui.c | 489 |
1 files changed, 283 insertions, 206 deletions
diff --git a/app/bin/paramfilesearch_ui.c b/app/bin/paramfilesearch_ui.c index bf9c47a..5050f22 100644 --- a/app/bin/paramfilesearch_ui.c +++ b/app/bin/paramfilesearch_ui.c @@ -2,7 +2,7 @@ * Parameter File Search Dialog */ -/* XTrkCad - Model Railroad CAD +/* XTrackCAD - Model Railroad CAD * Copyright (C) 2019 Martin Fischer * * This program is free software; you can redistribute it and/or modify @@ -17,165 +17,184 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include <assert.h> -#include <ctype.h> -#include <stdbool.h> -#include <stdint.h> -#include <string.h> - #include "custom.h" #include "dynstring.h" -#include "i18n.h" -#include "messages.h" #include "param.h" #include "include/partcatalog.h" #include "paths.h" #include "include/paramfilelist.h" +#include "include/paramfile.h" #include "fileio.h" #include "directory.h" +#include "layout.h" -#include "bitmaps/magnifier.xpm" - -static CatalogEntry *catalogFileBrowse; /**< current search results */ -static TrackLibrary *trackLibrary; /**< Track Library */ -static CatalogEntry *currentCat; /**< catalog being shown */ +static ParameterLib *trackLibrary; /**< Track Library */ +static Catalog currentCat; /**< catalog being shown */ /* define the search / browse dialog */ -static struct wFilSel_t *searchUi_fs; /**< searchdialog for parameter files */ - -static void SearchUiBrowse(void *junk); -static void SearchUiDefault(void * junk); +static void SearchUiDefault(void); static void SearchUiApply(wWin_p junk); static void SearchUiSelectAll(void *junk); static void SearchUiDoSearch(void *junk); +static void SearchUiClearFilter(void *ptr); static long searchUiMode = 0; +static long searchFitMode = 0; static paramListData_t searchUiListData = { 10, 370, 0 }; #define MAXQUERYLENGTH 250 static char searchUiQuery[MAXQUERYLENGTH]; static char * searchUiLabels[] = { N_("Show File Names"), NULL }; +// Note these are defined in the same order as FIT_ANY, FIT_COMPATIBLE, FIT_EXACT +static char * searchFitLabels[] = { N_("Fit Any"), N_("Fit Compatible"), N_("Fit Exact"), NULL}; + + +#define QUERYPROMPTSTRING "Enter at least one search word" static paramData_t searchUiPLs[] = { #define I_QUERYSTRING (0) - { PD_STRING, searchUiQuery, "query", PDO_NOPREF | PDO_STRINGLIMITLENGTH, (void*)(340), "", 0, 0, MAXQUERYLENGTH-1 }, + { PD_STRING, searchUiQuery, "query", PDO_ENTER | PDO_NOPREF | PDO_STRINGLIMITLENGTH | PDO_DLGRESIZE, I2VP(340), "", 0, 0, MAXQUERYLENGTH-1 }, #define I_SEARCHBUTTON (1) - { PD_BUTTON, (void*)SearchUiDoSearch, "find", PDO_DLGHORZ, 0, NULL, BO_ICON, (void *)NULL }, -#define I_MESSAGE (2) - { PD_MESSAGE, N_("Enter at least one search word"), NULL, PDO_DLGBOXEND, (void *)370 }, -#define I_RESULTLIST (3) - { PD_LIST, NULL, "inx", PDO_NOPREF | PDO_DLGRESIZE, &searchUiListData, NULL, BL_DUP|BL_SETSTAY|BL_MANY }, -#define I_MODETOGGLE (4) - { PD_TOGGLE, &searchUiMode, "mode", PDO_DLGBOXEND, searchUiLabels, NULL, BC_HORZ|BC_NOBORDER }, -#define I_APPLYBUTTON (5) - { PD_BUTTON, (void *)SearchUiApply, "apply", PDO_DLGCMDBUTTON, NULL, N_("Add") }, -#define I_SELECTALLBUTTON (6) - { PD_BUTTON, (void*)SearchUiSelectAll, "selectall", PDO_DLGCMDBUTTON, NULL, N_("Select all") }, - { PD_BUTTON, (void*)SearchUiDefault, "default", 0, NULL, N_("Reload Library") }, + { PD_BUTTON, SearchUiDoSearch, "find", PDO_DLGHORZ, 0, NULL, BO_ICON, NULL }, +#define I_CLEARBUTTON (2) + { PD_BUTTON, SearchUiClearFilter, "clearfilter", PDO_DLGHORZ, 0, NULL, BO_ICON, NULL }, +#define I_FITRADIO (3) + { PD_RADIO, &searchFitMode, "fit", PDO_NOPREF | PDO_DLGBOXEND, searchFitLabels, NULL, BC_HORZ|BC_NOBORDER }, +#define I_MESSAGE (4) + { PD_MESSAGE, N_(QUERYPROMPTSTRING), NULL, 0, I2VP(370) }, +#define I_STATISTICS (5) + { PD_MESSAGE, "", NULL, PDO_DLGBOXEND, I2VP(370) }, +#define I_RESULTLIST (6) + { PD_LIST, NULL, "inx", PDO_NOPREF | PDO_DLGRESIZE, &searchUiListData, NULL, BL_DUP|BL_SETSTAY|BL_MANY }, +#define I_MODETOGGLE (7) + { PD_TOGGLE, &searchUiMode, "mode", PDO_DLGBOXEND, searchUiLabels, NULL, BC_HORZ|BC_NOBORDER }, +#define I_APPLYBUTTON (8) + { PD_BUTTON, SearchUiApply, "apply", PDO_DLGCMDBUTTON, NULL, N_("Add") }, +#define I_SELECTALLBUTTON (9) + { PD_BUTTON, SearchUiSelectAll, "selectall", PDO_DLGCMDBUTTON, NULL, N_("Select all") }, }; #define SEARCHBUTTON ((wButton_p)searchUiPLs[I_SEARCHBUTTON].control) +#define CLEARBUTTON ((wButton_p)searchUiPLs[I_CLEARBUTTON].control) #define RESULTLIST ((wList_p)searchUiPLs[I_RESULTLIST].control) #define APPLYBUTTON ((wButton_p)searchUiPLs[I_APPLYBUTTON].control) #define SELECTALLBUTTON ((wButton_p)searchUiPLs[I_SELECTALLBUTTON].control) #define MESSAGETEXT ((wMessage_p)searchUiPLs[I_MESSAGE].control) #define QUERYSTRING ((wString_p)searchUiPLs[I_QUERYSTRING].control) +#define SEARCHSTAT ((wMessage_p)searchUiPLs[I_STATISTICS].control) +#define FITRADIO ((wChoice_p)searchUiPLs[I_FITRADIO].control) -static paramGroup_t searchUiPG = { "searchgui", 0, searchUiPLs, sizeof searchUiPLs/sizeof searchUiPLs[0] }; +static paramGroup_t searchUiPG = { "searchgui", 0, searchUiPLs, COUNT( searchUiPLs ) }; static wWin_p searchUiW; #define FILESECTION "file" #define PARAMDIRECTORY "paramdir" + /** - * Reload the listbox showing the current catalog + * Clears the current catalog */ -static -void SearchFileListLoad(CatalogEntry *catalog) +void +ClearCurrentCatalog(void) { - CatalogEntry *currentEntry = catalog->next; - DynString description; - DynStringMalloc(&description, STR_SHORT_SIZE); - - wControlShow((wControl_p)RESULTLIST, FALSE); - wListClear(RESULTLIST); - - while (currentEntry != currentEntry->next) { - for (unsigned int i=0;i<currentEntry->files;i++) { - DynStringClear(&description); - DynStringCatCStr(&description, - ((!searchUiMode) && currentEntry->contents) ? - currentEntry->contents : - currentEntry->fullFileName[i]); - - wListAddValue(RESULTLIST, - DynStringToCStr(&description), - NULL, - // indicatorIcons[paramFileInfo.favorite][paramFileInfo.trackState], - (void*)currentEntry->fullFileName[i]); - } - - currentEntry = currentEntry->next; - } - - wControlShow((wControl_p)RESULTLIST, TRUE); - wControlActive((wControl_p)SELECTALLBUTTON, - wListGetCount(RESULTLIST)); - - DynStringFree(&description); - - currentCat = catalog; + if (currentCat.head) { + DestroyCatalog(¤tCat); + currentCat.head = NULL; + } } /** - * Find parameter files using the file selector + * Reload the listbox showing the current catalog. The catalog is either the system + * default library catalog or a search result * - * \param junk + * \param [in] catalog the current catalog. */ -static void SearchUiBrowse(void * junk) -{ +static +int SearchFileListLoad(Catalog *catalog) - //EmptyCatalog(catalogFileBrowse); +{ + CatalogEntry *head = catalog->head; + CatalogEntry *catalogEntry; + + DynString description; + DynStringMalloc(&description, STR_SHORT_SIZE); + + wControlShow((wControl_p)RESULTLIST, FALSE); + wListClear(RESULTLIST); + + DL_FOREACH(head, catalogEntry) { + for (unsigned int i=0; i<catalogEntry->files; i++) { + if (catalogEntry->tag && searchFitMode != 0) { + char * type_copy = MyStrdup(catalogEntry->tag); + char * cp = type_copy; + char * type = strtok(cp, " \t"); + SCALE_FIT_TYPE_T fit_type; + if (strcmp(type,TURNOUTCOMMAND) == 0) { + fit_type = FIT_TURNOUT; + } else if (strcmp(type,STRUCTURECOMMAND)==0) { + fit_type = FIT_STRUCTURE; + } else if ((strcmp(type,CARCOMMAND)==0) || (strcmp(type,CARPROTOCOMMAND)==0)) { + fit_type = FIT_CAR; + } + char * scale = strtok(NULL, " \t\n"); + if (scale) { + SCALEINX_T scale1 = LookupScale(scale); + SCALEINX_T scale2 = GetLayoutCurScale(); + if (searchFitMode == FIT_COMPATIBLE) { + if (CompatibleScale(fit_type,scale1,scale2)<FIT_COMPATIBLE) { continue; } + } else { + if (CompatibleScale(fit_type,scale1,scale2)<FIT_EXACT) { continue; } + } + + } + MyFree(type_copy); + } + DynStringClear(&description); + DynStringCatCStr(&description, + ((!searchUiMode) && catalogEntry->contents) ? + catalogEntry->contents : + catalogEntry->fullFileName[i]); - wFilSelect(searchUi_fs, GetParamFileDir()); + wListAddValue(RESULTLIST, + DynStringToCStr(&description), + NULL, + catalogEntry->fullFileName[i]); + } + } - //SearchFileListLoad(catalogFileBrowse); + wControlShow((wControl_p)RESULTLIST, TRUE); + wControlActive((wControl_p)SELECTALLBUTTON, + wListGetCount(RESULTLIST)); - return; + DynStringFree(&description); + return wListGetCount(RESULTLIST); } - /** * Reload just the system files into the searchable set */ -static void SearchUiDefault(void * junk) +static void SearchUiDefault(void) { + DynString dsSummary; - if (!catalogFileBrowse) - catalogFileBrowse = InitCatalog(); - else { - EmptyCatalog(catalogFileBrowse); - } - - if (trackLibrary) - DeleteLibrary(trackLibrary); - - char * parms_path; - - MakeFullpath(&parms_path, wGetAppLibDir(), "params", NULL); + int matches = SearchFileListLoad( + trackLibrary->catalog); //Start with system files + wStringSetValue(QUERYSTRING, ""); - trackLibrary = CreateLibrary(parms_path); - - SearchFileListLoad(trackLibrary->catalog); //Start with system files - - free(parms_path); + wMessageSetValue(MESSAGETEXT, _(QUERYPROMPTSTRING)); + DynStringMalloc(&dsSummary, 16); + DynStringPrintf(&dsSummary, _("%u parameter files in library. %d Fit Scale."), + CountCatalogEntries(trackLibrary->catalog), matches); + wMessageSetValue(SEARCHSTAT, DynStringToCStr(&dsSummary)); + DynStringFree(&dsSummary); + wControlActive((wControl_p)CLEARBUTTON, FALSE); } /** @@ -185,27 +204,23 @@ static void SearchUiDefault(void * junk) void static SearchUILoadResults(void) { - char **fileNames; - int files = wListGetSelectedCount(RESULTLIST); - int found = 0; - - if (files) { - fileNames = malloc(sizeof(char *)*files); - if (!fileNames) { - AbortProg("Couldn't allocate memory for result list: %s (%d)", __FILE__, - __LINE__, NULL); - } - - for (int inx = 0; found < files; inx++) { - if (wListGetItemSelected(RESULTLIST, inx)) { - fileNames[found++] = (char *)wListGetItemContext(RESULTLIST, inx); - } - } - - LoadParamFile(files, fileNames, NULL); - free(fileNames); - SearchUiOk((void *) 0); - } + int files = wListGetSelectedCount(RESULTLIST); + + if (files) { + char **fileNames; + int found = 0; + fileNames = MyMalloc(sizeof(char *)*files); + + for (int inx = 0; found < files; inx++) { + if (wListGetItemSelected(RESULTLIST, inx)) { + fileNames[found++] = (char *)wListGetItemContext(RESULTLIST, inx); + } + } + + LoadParamFile(files, fileNames, NULL); + MyFree(fileNames); + SearchUiOk(NULL); + } } @@ -220,69 +235,104 @@ SearchUILoadResults(void) static void UpdateSearchUiButton(void) { - wIndex_t selCnt = wListGetSelectedCount(RESULTLIST); - wIndex_t cnt = wListGetCount(RESULTLIST); + wIndex_t selCnt = wListGetSelectedCount(RESULTLIST); + wIndex_t cnt = wListGetCount(RESULTLIST); - wControlActive((wControl_p)APPLYBUTTON, selCnt > 0); - wControlActive((wControl_p)SELECTALLBUTTON, cnt > 0); + wControlActive((wControl_p)APPLYBUTTON, selCnt > 0); + wControlActive((wControl_p)SELECTALLBUTTON, cnt > 0); } -// Return a pointer to the (shifted) trimmed string +/** + * Return a pointer to the (shifted) trimmed string + * + * \param [in,out] s If non-null, a char to process. + * + * \returns pointer to the trimmed string + */ + char * StringTrim(char *s) { - char *original = s; - size_t len = 0; - - while (isspace((unsigned char) *s)) { - s++; - } - if (*s) { - char *p = s; - while (*p) p++; - while (isspace((unsigned char) *(--p))); - p[1] = '\0'; - len = (size_t) (p - s + 1); - } - - return (s == original) ? s : memmove(original, s, len + 1); + char *original = s; + size_t len = 0; + + while (isspace((unsigned char) *s)) { + s++; + } + if (*s) { + char *p = s; + while (*p) { + p++; + } + while (isspace((unsigned char) *(--p))); + p[1] = '\0'; + len = (size_t)(p - s + 1); + } + + return (s == original) ? s : memmove(original, s, len + 1); } /** * Perform the search. If successful, the results are loaded into the list * - * \param ptr INignored + * \param [in,out] ptr ignored. */ static void SearchUiDoSearch(void * ptr) { - unsigned result; + unsigned result; + SearchResult *currentResults = MyMalloc(sizeof(SearchResult)); + char * search; + + ClearCurrentCatalog(); + + strcpy(searchUiQuery, wStringGetValue((wString_p) + searchUiPG.paramPtr[I_QUERYSTRING].control)); + search = StringTrim(searchUiQuery); + + if (search[0]) { + result = SearchLibrary(trackLibrary, search, currentResults); - char * search; + if (result) { - search = StringTrim(searchUiQuery); + char *statistics; - if (catalogFileBrowse) { - EmptyCatalog(catalogFileBrowse); - } else - catalogFileBrowse = InitCatalog(); + statistics = SearchStatistics(currentResults); + wMessageSetValue(SEARCHSTAT, statistics); + MyFree(statistics); - result = SearchLibrary(trackLibrary, search, catalogFileBrowse); + int matches = SearchFileListLoad(&(currentResults->subCatalog)); - if (result) { - DynString hitsMessage; - DynStringMalloc(&hitsMessage, 16); - DynStringPrintf(&hitsMessage, _("%d parameter files found."), result); - wMessageSetValue(MESSAGETEXT, DynStringToCStr(&hitsMessage)); - DynStringFree(&hitsMessage); + DynString hitsMessage; + DynStringMalloc(&hitsMessage, 16); + DynStringPrintf(&hitsMessage, _("%d parameter files found. %d Fit Scale"), + result, matches); + wMessageSetValue(MESSAGETEXT, DynStringToCStr(&hitsMessage)); + DynStringFree(&hitsMessage); - SearchFileListLoad(catalogFileBrowse); + currentCat = currentResults->subCatalog; + wControlActive((wControl_p)CLEARBUTTON, TRUE); + } else { + wListClear(RESULTLIST); + wControlActive((wControl_p)SELECTALLBUTTON, FALSE); + wMessageSetValue(MESSAGETEXT, _("No matches found.")); + } + } else { + SearchUiDefault(); + } + MyFree(currentResults); //Because SearchFileList also caches the currentResults->subCatalog address as currentCatalog for reuse. +} - } else { +/** + * Clear the current filter + * + * \param [in,out] ptr ignored + */ - wListClear(RESULTLIST); - wControlActive((wControl_p)SELECTALLBUTTON, FALSE); - wMessageSetValue(MESSAGETEXT, _("No matches found.")); - } +static void +SearchUiClearFilter(void *ptr) +{ + ClearCurrentCatalog(); + SearchUiDefault(); } /** @@ -294,7 +344,7 @@ static void SearchUiDoSearch(void * ptr) static void SearchUiSelectAll(void *junk) { - wListSelectAll(RESULTLIST); + wListSelectAll(RESULTLIST); } /** @@ -305,9 +355,9 @@ static void SearchUiSelectAll(void *junk) void SearchUiOk(void * junk) { - if (searchUiW) { - wHide(searchUiW); - } + if (searchUiW) { + wHide(searchUiW); + } } /** @@ -319,11 +369,11 @@ void SearchUiOk(void * junk) static void SearchUiApply(wWin_p junk) { - SearchUILoadResults(); + SearchUILoadResults(); } /** - * Event handling for the Search dialog. If the 'X' decoration is pressed the + * Event handling for the Search dialog. If the 'X' decoration is pressed the * dialog window is closed. * * \param pg IN ignored @@ -332,25 +382,47 @@ static void SearchUiApply(wWin_p junk) */ static void SearchUiDlgUpdate( - paramGroup_p pg, - int inx, - void * valueP) + paramGroup_p pg, + int inx, + void * valueP) { - switch (inx) { - case I_RESULTLIST: - UpdateSearchUiButton(); - break; - case I_MODETOGGLE: - SearchFileListLoad(currentCat); - break; + switch (inx) { + case I_QUERYSTRING: + if (pg->paramPtr[inx].enter_pressed) { + strcpy( searchUiQuery, wStringGetValue((wString_p)pg->paramPtr[inx].control) ); + SearchUiDoSearch(NULL); + } + break; + case I_RESULTLIST: + UpdateSearchUiButton(); + break; + case I_FITRADIO: + strcpy( searchUiQuery, wStringGetValue((wString_p) + pg->paramPtr[I_QUERYSTRING].control) ); + SearchUiDoSearch(NULL); + break; + case I_MODETOGGLE: + if (currentCat.head) { + SearchFileListLoad(¤tCat); + } else { + SearchFileListLoad(trackLibrary->catalog); + } + break; case -1: SearchUiOk(valueP); break; - } + } +} + +void +SearchUiCancel(wWin_p window) +{ + ClearCurrentCatalog(); + wHide(window); } /** - * Get the system default directory for parameter files. First step is to + * Get the system default directory for parameter files. First step is to * check the configuration file for a user specific setting. If that is not * found, the diretory is based derived from the installation directory. * The returned string has to be free'd() when no longer needed. @@ -370,8 +442,12 @@ GetParamsPath() } else { params_path = strdup(params_pref); } - return(params_path); + return (params_path); } + +#include "bitmaps/funnel.xpm" +#include "bitmaps/funnelclear.xpm" + /** * Create and open the search dialog. * @@ -380,47 +456,48 @@ GetParamsPath() void DoSearchParams(void * junk) { - if (searchUiW == NULL) { - catalogFileBrowse = InitCatalog(); + if (searchUiW == NULL) { - //Make the Find menu bound to the System Library initially + //Make the Find menu bound to the System Library initially char *paramsDir = GetParamsPath(); - trackLibrary = CreateLibrary(paramsDir); + trackLibrary = CreateLibrary(paramsDir); free(paramsDir); - searchUiPLs[I_SEARCHBUTTON].winLabel = (char *)wIconCreatePixMap(magnifier_xpm); + searchUiPLs[I_SEARCHBUTTON].winLabel = (char *)wIconCreatePixMap(funnel_xpm); + searchUiPLs[I_CLEARBUTTON].winLabel = (char *)wIconCreatePixMap( + funnelclear_xpm); - ParamRegister(&searchUiPG); + searchFitMode = FIT_COMPATIBLE; //Default to "Any" after startup - searchUiW = ParamCreateDialog(&searchUiPG, - MakeWindowTitle(_("Choose parameter files")), _("Done"), NULL, wHide, - TRUE, NULL, F_RESIZE | F_RECALLSIZE, SearchUiDlgUpdate); - if (trackLibrary) { - SearchFileListLoad(trackLibrary->catalog); //Start with system files - } - wControlActive((wControl_p)APPLYBUTTON, FALSE); - wControlActive((wControl_p)SELECTALLBUTTON, FALSE); + ParamRegister(&searchUiPG); + + + + searchUiW = ParamCreateDialog(&searchUiPG, + MakeWindowTitle(_("Choose parameter files")), _("Done"), NULL, SearchUiCancel, + TRUE, NULL, F_RESIZE | F_RECALLSIZE, SearchUiDlgUpdate); - searchUi_fs = wFilSelCreate(searchUiW, FS_LOAD, FS_MULTIPLEFILES, - _("Load Parameters"), _("Parameter files (*.xtp)|*.xtp"), GetParameterFileInfo, - (void *)catalogFileBrowse); - } - ParamLoadControls(&searchUiPG); - ParamGroupRecord(&searchUiPG); + wControlActive((wControl_p)APPLYBUTTON, FALSE); + wControlActive((wControl_p)SELECTALLBUTTON, FALSE); + } + + wControlActive((wControl_p)FITRADIO, TRUE); + + ParamLoadControls(&searchUiPG); + ParamGroupRecord(&searchUiPG); - if (!trackLibrary) { - wControlActive((wControl_p)SEARCHBUTTON, FALSE); - wControlActive((wControl_p)QUERYSTRING, FALSE); - wMessageSetValue(MESSAGETEXT, - _("No system parameter files found, search is disabled.")); - } else { - wStringSetValue(QUERYSTRING, ""); - SearchFileListLoad(trackLibrary->catalog); //Start with system files + if (!trackLibrary) { + wControlActive((wControl_p)SEARCHBUTTON, FALSE); + wControlActive((wControl_p)QUERYSTRING, FALSE); + wMessageSetValue(MESSAGETEXT, + _("No system parameter files found, search is disabled.")); + } else { + SearchUiDefault(); + } - } - wShow(searchUiW); + wShow(searchUiW); } |