/** \file paramfilesearch_ui.c * Parameter File Search Dialog */ /* XTrkCad - Model Railroad CAD * Copyright (C) 2019 Martin Fischer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * 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. */ #include #include #include #include #include #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 "fileio.h" #include "directory.h" #include "bitmaps/magnifier.xpm" static CatalogEntry *catalogFileBrowse; /**< current search results */ static TrackLibrary *trackLibrary; /**< Track Library */ static CatalogEntry *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 SearchUiApply(wWin_p junk); static void SearchUiSelectAll(void *junk); static void SearchUiDoSearch(void *junk); static long searchUiMode = 0; static paramListData_t searchUiListData = { 10, 370, 0 }; #define MAXQUERYLENGTH 250 static char searchUiQuery[MAXQUERYLENGTH]; static char * searchUiLabels[] = { N_("Show File Names"), NULL }; static paramData_t searchUiPLs[] = { #define I_QUERYSTRING (0) { PD_STRING, searchUiQuery, "query", PDO_NOPREF | PDO_STRINGLIMITLENGTH, (void*)(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") }, }; #define SEARCHBUTTON ((wButton_p)searchUiPLs[I_SEARCHBUTTON].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) static paramGroup_t searchUiPG = { "searchgui", 0, searchUiPLs, sizeof searchUiPLs/sizeof searchUiPLs[0] }; static wWin_p searchUiW; #define FILESECTION "file" #define PARAMDIRECTORY "paramdir" /** * Reload the listbox showing the current catalog */ static void SearchFileListLoad(CatalogEntry *catalog) { 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;ifiles;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; } /** * Find parameter files using the file selector * * \param junk */ static void SearchUiBrowse(void * junk) { //EmptyCatalog(catalogFileBrowse); wFilSelect(searchUi_fs, GetParamFileDir()); //SearchFileListLoad(catalogFileBrowse); return; } /** * Reload just the system files into the searchable set */ static void SearchUiDefault(void * junk) { if (!catalogFileBrowse) catalogFileBrowse = InitCatalog(); else { EmptyCatalog(catalogFileBrowse); } if (trackLibrary) DeleteLibrary(trackLibrary); char * parms_path; MakeFullpath(&parms_path, wGetAppLibDir(), "params", NULL); trackLibrary = CreateLibrary(parms_path); SearchFileListLoad(trackLibrary->catalog); //Start with system files free(parms_path); } /** * Load the selected items of search results */ 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); } } /** * Update the action buttons. * * If there is at least one selected file, Apply is enabled * If there are entries in the list, Select All is enabled * * \return */ static void UpdateSearchUiButton(void) { wIndex_t selCnt = wListGetSelectedCount(RESULTLIST); wIndex_t cnt = wListGetCount(RESULTLIST); wControlActive((wControl_p)APPLYBUTTON, selCnt > 0); wControlActive((wControl_p)SELECTALLBUTTON, cnt > 0); } // Return a pointer to the (shifted) 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); } /** * Perform the search. If successful, the results are loaded into the list * * \param ptr INignored */ static void SearchUiDoSearch(void * ptr) { unsigned result; char * search; search = StringTrim(searchUiQuery); if (catalogFileBrowse) { EmptyCatalog(catalogFileBrowse); } else catalogFileBrowse = InitCatalog(); result = SearchLibrary(trackLibrary, search, catalogFileBrowse); if (result) { DynString hitsMessage; DynStringMalloc(&hitsMessage, 16); DynStringPrintf(&hitsMessage, _("%d parameter files found."), result); wMessageSetValue(MESSAGETEXT, DynStringToCStr(&hitsMessage)); DynStringFree(&hitsMessage); SearchFileListLoad(catalogFileBrowse); } else { wListClear(RESULTLIST); wControlActive((wControl_p)SELECTALLBUTTON, FALSE); wMessageSetValue(MESSAGETEXT, _("No matches found.")); } } /** * Select all files in the list * * \param junk IN ignored * \return */ static void SearchUiSelectAll(void *junk) { wListSelectAll(RESULTLIST); } /** * Action handler for Done button. Hides the dialog. * * \param [in,out] junk ignored. */ void SearchUiOk(void * junk) { if (searchUiW) { wHide(searchUiW); } } /** * Handle the Add button: a list of selected list elements is created and * passed to the parameter file list. * * \param junk IN/OUT ignored */ static void SearchUiApply(wWin_p junk) { SearchUILoadResults(); } /** * Event handling for the Search dialog. If the 'X' decoration is pressed the * dialog window is closed. * * \param pg IN ignored * \param inx IN ignored * \param valueP IN ignored */ static void SearchUiDlgUpdate( paramGroup_p pg, int inx, void * valueP) { switch (inx) { case I_RESULTLIST: UpdateSearchUiButton(); break; case I_MODETOGGLE: SearchFileListLoad(currentCat); break; case -1: SearchUiOk(valueP); break; } } /** * 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. * * \return parameter file directory */ static char * GetParamsPath() { char * params_path; char *params_pref; params_pref = wPrefGetString(FILESECTION, PARAMDIRECTORY); if (!params_pref) { MakeFullpath(¶ms_path, wGetAppLibDir(), "params", NULL); } else { params_path = strdup(params_pref); } return(params_path); } /** * Create and open the search dialog. * * \param junk */ void DoSearchParams(void * junk) { if (searchUiW == NULL) { catalogFileBrowse = InitCatalog(); //Make the Find menu bound to the System Library initially char *paramsDir = GetParamsPath(); trackLibrary = CreateLibrary(paramsDir); free(paramsDir); searchUiPLs[I_SEARCHBUTTON].winLabel = (char *)wIconCreatePixMap(magnifier_xpm); ParamRegister(&searchUiPG); 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); searchUi_fs = wFilSelCreate(searchUiW, FS_LOAD, FS_MULTIPLEFILES, _("Load Parameters"), _("Parameter files (*.xtp)|*.xtp"), GetParameterFileInfo, (void *)catalogFileBrowse); } 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 } wShow(searchUiW); }