This week, we’ll be introducing a script that adds a very handy feature to GoFiler: the ability to save, load, and edit preference templates. These preference templates will include settings like your EDGAR credentials, HTML conversion settings, and default options for edit windows.
Friday, April 06. 2018
LDC #79: Save, Load, and Edit Preferences Templates
Preferences in GoFiler are stored in a file called “GoFiler Complete Settings.ini”. If we want to keep a version of those settings, all we need to do is copy that file. To load a preference template, we can restore the original file by writing the copy back to the “GoFiler Complete Settings.ini” file. If the application is open, we will then have to force the software to reload the application preferences.
To make this script a little more useful, we’ll also keep a list of all the template files we’ve created (and their user defined names) so we can view all of them easily and select one to load. We can also make functions to delete and rename templates to enrich the user experience. None of these functions are overly complicated themselves, but this is going to involve several parts with multiple dialog boxes, making it a bit more complex than the average script we show here.
Let's start by taking a look at the defines and heading information. Most of them are just error messages or warnings. It’s always a good idea to use defined values for messages, in case you want to repeat the message, or want to change it later. It also makes it a lot easier to read the code if you don’t have large string values in there taking up space. The define TEMPLATE_REGEX is a regular expression used to check for valid template names, and ENABLE_WARN is a boolean value that can be switched to false in order to disable warnings that pop up when filing to the SEC. In this section, we also have our global values, renaming and old_name. The global renaming is a boolean and is true if we’re renaming a file. We need to use a global for this because the Save Template dialog is used for both saving new ones and renaming old ones, so we can just toggle that flag to let it do slightly different things based on the operation. Our other global, old_name, is also used in renaming; it’s just the name of the template we’re going to rename.
#define PREFS_FILE "preference_templates.csv" #define TEMPLATE_REGEX "^[a-zA-Z\\d\\s]+$" #define READ_TEMPLATE_ERR "Cannot read template file, error code %0x" #define INVALID_NAME_ERR "Template names must be only letters, numbers, and spaces." #define TEMPLATE_EXISTS_ERR "Template with the name \"%s\" already exists. Overwrite?" #define TEMPLATE_EXISTS_ERR_F "Template with the name \"%s\" already exists." #define NO_TEMPLATES_EXIST_ERR "Cannot load or edit templates, no templates exist." #define RENAME_ERR "Cannot rename template, error code %0x." #define COPY_ERR "Cannot save new template, error %0x" #define LOAD_ERR "Cannot load existing template, error %0x" #define NO_TEMPLATE_SELECT "Must select a valid template before continuing." #define SUCCESS_MSG "Loaded preferences template \"%s\" successfully." #define DELETE_MSG "This will delete the preference template \"%s\". Continue?" #define DELETE_ERR "Cannot delete %s, error: %0x" #define FILE_WARNING "Submission will be filed by CIK %s. Continue?" #define ENABLE_WARN true /* true to warn on filing what the profile is */ [.. removed function definitions here ..] boolean renaming; /* true if renaming a file */ string old_name; /* the previous name in a renamed file */
The setup function is pretty familiar, but it has a few extra bells and whistles. First of all, it checks to see if there’s a file named “DefaultSettings.ini” in the templates folder of the script execution directory. If there is, it means GoFiler is using a default settings template usually defined by an enterprise or department. If that’s the case, you don’t want a user to destroy or edit any settings, so it just aborts the setup and never actually hooks anything. Next, we set up our three menu functions to save, load, and edit our templates. Lastly, we check if our warnings are enabled, and, if so, hook our warning function run_warn to GoFiler’s file to SEC functions. We need to warn the user because they might have forgotten what template they have loaded, and it’s better to be safe than sorry when it comes to SEC filings.
/****************************************/ void setup() { /* Called from Application Startup */ /****************************************/ string fn; /* file name */ string item[10]; /* menu item array */ string settings; /* the settings file location */ string gf_folder; /* gofiler execution folder */ /* */ gf_folder = GetApplicationExecuteFolder(); /* get the execution folder */ settings =AddPaths(gf_folder,"Templates\\DefaultSettings.ini"); /* path to the default settings file */ if(IsFile(settings)==true){ /* if default settings exist */ return ERROR_NONE; /* don't use this script. */ } /* */ /* */ item["Code"] = "SAVE_PREFERENCES"; /* set hook code */ item["Description"] = "Save the current set of preferences"; /* set hook description */ item["MenuText"] = "Save Preferences"; /* set menu text */ MenuAddFunction(item); /* add menu item to menu */ fn = GetScriptFilename(); /* get the filename of the script */ MenuSetHook("SAVE_PREFERENCES", fn, "run_save"); /* set the hook */ /* */ item["Code"] = "LOAD_PREFERENCES"; /* set hook code */ item["Description"] = "Load a new set of preferences."; /* set hook description */ item["MenuText"] = "Load Preferences"; /* set menu text */ MenuAddFunction(item); /* add menu function */ MenuSetHook("LOAD_PREFERENCES", fn, "run_load"); /* set the hook */ /* */ item["Code"] = "MODIFY_PREFERENCES"; /* set the hook code */ item["Description"] = "Edit or delete saved preferences."; /* set the hook description */ item["MenuText"] = "Modify Preferences"; /* set the menu text */ MenuAddFunction(item); /* add to menu */ MenuSetHook("MODIFY_PREFERENCES", fn, "run_mod"); /* set the hook to menu item */ /* */ if (ENABLE_WARN){ /* if warnings are enabled */ MenuSetHook("EDGAR_SUBMIT_TEST", fn, "run_warn"); /* add the warning */ MenuSetHook("EDGAR_SUBMIT_LIVE", fn, "run_warn"); /* add the warning */ MenuSetHook("NSS_SUBMIT_DELAY", fn, "run_warn"); /* add the warning */ MenuSetHook("EDGAR_SUBMIT_TEST_AGENT", fn, "run_warn"); /* add the warning */ } /* */ } /* */
The run_warn function is going to run preprocess for every filing to the SEC. It checks your applications data folder for a file named “PreferencesSwitcher.ini”. This file should only exist if the save template hook has been used previously. If that file doesn’t exist, we can exit here; we don’t need to warn anyone because there are no templates in use. Otherwise, we can ask the user if he wants to proceed, and if he doesn’t click yes, we can exit.
/****************************************/ int run_warn(int f_id, string mode){ /* run the warnings */ /****************************************/ int rc; /* result code */ string appdata; /* appdata folder location */ /* */ if (mode!="preprocess"){ /* if not in preprocess */ return; /* exit */ } /* */ appdata = GetApplicationDataFolder(); /* get the appdata folder */ if (IsFile(AddPaths(appdata,"PreferencesSwitcher.ini"))==false){ /* if it's not a file */ return; /* script not in use, so return */ } /* otherwise, script in use, so cont. */ rc = YesNoBox('i',FILE_WARNING,EDGARGetLoginCIK()); /* display warning */ if (rc!=IDYES){ /* if user doesn't press yes */ return ERROR_EXIT; /* abort filing process */ } /* */ } /* */
The clean_blank_rows function is a little subroutine in here to clean blank rows out of our CSV file, holding the names of the templates. It just reads the file in, replaces all the blank rows with nothing, and then writes the modified file back out. In future versions of Legato we’ll be adding more graceful ways to remove rows from CSV files, but this works for now.
/****************************************/ void clean_blank_rows(){ /* clean up blank rows in prefs CSV */ /****************************************/ string file; /* file contents */ string appdata; /* appdata folder */ string filename; /* path to file */ /* */ appdata = GetApplicationDataFolder(); /* get the appdata folder location */ filename = AddPaths(appdata,PREFS_FILE); /* get path to the file */ if (IsFile(filename)){ /* if the file exists */ file = FileToString(filename); /* get the contents of the file */ file = ReplaceInString(file,"\"\",\"\"\r",""); /* remove blank rows */ StringToFile(file,filename); /* write the contents back out */ } /* */ } /* */
The function run_save triggers our save dialog. This function checks to make sure it’s only running preprocess, sets the renaming flag to false, then enters the dialog box.
/****************************************/ void run_save(int f_id, string mode){ /* run the save function */ /****************************************/ if (mode != "preprocess"){ /* if not preprocess */ return; /* bail out */ } /* */ renaming = false; /* set renaming flag to false */ DialogBox(PREFERENCE_TEMPLATES, "save_"); /* enter the save dialog */ } /* */
The run_load function is similar to the run_save function, but before it enters the dialog box it gets the value of the number of templates using the GetSetting function, and checks if it’s 0 or doesn’t exist. If so, it displays an error message (because you cannot load a template if you don’t have any templates) and returns. Otherwise, it enters the load dialog.
/****************************************/ void run_load(int f_id, string mode){ /* run the load function */ /****************************************/ string num_templates; /* number of available templates */ /* */ if (mode != "preprocess"){ /* if not preprocess, bail out */ return; /* return */ } /* */ /* */ num_templates = GetSetting("Settings","num_templates"); /* get the number of templates in use */ if (num_templates == "" || num_templates =="0"){ /* if there are no templates */ MessageBox('x',NO_TEMPLATES_EXIST_ERR); /* display error */ return; /* return */ } /* */ DialogBox(CHANGE_PREFS,"load_"); /* enter the load dialog */ } /* */
Our run_mod function is essentially a copy/paste of the run_load function. It checks the number of templates, and then enters the modify dialog.
/****************************************/ void run_mod(int f_id, string mode){ /* run the modify function */ /****************************************/ string num_templates; /* number of templates */ /* */ if (mode != "preprocess"){ /* if not preprocess */ return; /* bail out */ } /* */ /* */ num_templates = GetSetting("Settings","num_templates"); /* get the number of templates */ if (num_templates == "" || num_templates =="0"){ /* if there are no templates */ MessageBox('x',NO_TEMPLATES_EXIST_ERR); /* display error */ return; /* return */ } /* */ DialogBox(MANAGE_TEMPLATES_DLG,"mod_"); /* enter the modify dialog */ } /* */
The mod_load function is called by Legato as part of the DialogBox function call in the run_mod function. The function runs before the dialog is actually displayed, and lets us set up the dialog. First, it runs DataControlResetContent to clear out any data in the table, then gets the path to our template CSV file. If the file exists, it can then set up the headings for our dialog’s data table with DataControlSetColumnHeadings and DataControlSetColumnPositions. Then we can iterate over all templates, and for each one that isn’t blank, use DataControlInsertString to insert it into our dialog.
/****************************************/ void mod_load(){ /* load the modify dialog contents */ /****************************************/ string templates[][]; /* templates CSV file contents */ string template_path; /* the path to the template CSV file */ string appdata; /* application data folder */ int ix; /* counter variable */ int num_templates; /* number of templates */ /* */ DataControlResetContent(TEMPLATE_LIST); /* reset contents of the dialog */ appdata = GetApplicationDataFolder(); /* get the appdata folder */ template_path = AddPaths(appdata,PREFS_FILE); /* get the path to the template CSV */ if (IsFile(template_path)){ /* if the file exists */ templates = CSVReadTable(template_path); /* read it's contents */ DataControlSetColumnHeadings(TEMPLATE_LIST,"Template Name"); /* set the heading for the data control */ DataControlSetColumnPositions(TEMPLATE_LIST, 167); /* set the width of the heading */ num_templates = ArrayGetAxisDepth(templates); /* get the number of templates */ for(ix=0;ix<num_templates;ix++){ /* for each template in the file */ if (templates[ix][0]!=""){ /* if the template isn't blank */ DataControlInsertString(TEMPLATE_LIST,ix,templates[ix][0]); /* add it to the dialog */ } /* */ } /* */ } /* */ } /* */
The mod_action function is called automatically by our Dialog Box, whenever a user does anything to the dialog. We don’t care if the user interacts with anything except two buttons, because only those buttons trigger further action. So the first thing the function needs to do is to check to see if the c_id is one of our two buttons. If the c_id is not TEMPLATE_RENAME or TEMPLATE_DELETE, we can just return. Otherwise, we need to get the selected value from our template list. If the value is less than zero, it means the user didn’t select anything, and we can display an error message and return.
Once we know the user clicked a button and has a valid selection, we can check if our button was TEMPLATE_RENAME, and if so, we run our rename function. If it was successful (returned without error), we can reload the list by running mod_load. We do the same check for TEMPLATE_DELETE and reload the list on success.
/****************************************/ void mod_action(int c_id, int action){ /* action on the modify dialog */ /****************************************/ string selected_nm; /* selected name */ int selected; /* selected index value */ string data[][]; /* content of the dialog's list */ int rc; /* result code */ /* */ if (c_id != TEMPLATE_RENAME && c_id != TEMPLATE_DELETE){ /* if not one of our two buttons */ return; /* return */ } /* */ /* */ selected = DataControlGetRowSelection(TEMPLATE_LIST); /* get the selected item from the list */ if(selected < 0){ /* if there no selection */ MessageBox('x',NO_TEMPLATE_SELECT); /* display error */ return; /* return */ } /* */ /* */ data = DataControlGetTable(TEMPLATE_LIST); /* get the data from the list */ selected_nm = data[selected][0]; /* get the name of the selected row */ if (c_id == TEMPLATE_RENAME){ /* if rename was pressed */ rc = rename(selected_nm); /* run the rename function */ if (IsError(rc)==false){ /* if rename didn't return an error */ mod_load(); /* reload the list */ } /* */ return; /* return */ } /* */ if (c_id == TEMPLATE_DELETE){ /* if delete was pressed */ rc = delete(selected_nm); /* run the delete function */ if (IsError(rc)==false){ /* if delete didn't return an error */ mod_load(); /* reload the list */ } /* */ return; /* return */ } /* */ } /* */
The rename function, when triggered, sets our globals to allow the save function to rename things correctly, then enters the save dialog. If the save failed, and it wasn’t a cancel operation, we can display an error and return the error. Otherwise, we can just return without error.
/****************************************/ int rename(string name){ /* rename a template */ /****************************************/ int rc; /* result code */ /* */ old_name = name; /* store the previous name */ renaming = true; /* set rename flag for save function */ rc = DialogBox(PREFERENCE_TEMPLATES, "save_"); /* enter the save dialog */ if (IsError(rc) && rc!=ERROR_CANCEL){ /* if it was an error other than cancel */ MessageBox('x',RENAME_ERR,rc); /* display error */ return rc; /* return the error */ } /* */ return ERROR_NONE; /* return without error */ } /* */
The delete function needs to remove the template from our CSV file and delete the template file it created. Since we use the delete function as part of the rename function, we need to skip the user confirmation when a rename operation is occurring. In this way, the user will not see a message box asking him if he wants to delete a file when he is in the process of renaming it.
The next step is to get the template CSV file location, check to make sure the file exists, and read it. We need to find the row of the template we’re deleting by using the FindInTable function. That row has the file name for our template, so we can now run the DeleteFile function to kill it. We can blank out that row of our table, and use CSVWriteTable to write the file containing the template list back out. If our write file failed, we display an error and return.
Next, we need to check if the deleted template was the active template. If so, we need to mark the active template as blank, decrement the number of available templates, and run our clean_blank_rows function to ensure there are no blank rows in our CSV file.
/****************************************/ int delete(string name){ /* delete a template */ /****************************************/ int rc; /* result code */ string appdata; /* appdata folder */ string template_path; /* path to the template CSV file */ string templates[][]; /* contents of template CSV file */ string current_template; /* currently active template */ int template_row; /* id of the row in the CSV */ int num_templates; /* number of templates */ /* */ if (renaming){ /* if renaming the template */ rc = IDYES; /* assume yes to dialog */ } /* */ else{ /* if not in the middle of a rename */ rc = YesNoBox('q',DELETE_MSG,name); /* ask to confirm delete */ } /* */ if (rc!=IDYES){ /* if the user didn't press yes */ return ERROR_EXIT; /* exit with error */ } /* */ appdata = GetApplicationDataFolder(); /* get the application data area */ template_path = AddPaths(appdata,PREFS_FILE); /* get the path to the template CSV */ if (IsFile(template_path)){ /* if the file exists */ templates = CSVReadTable(template_path); /* read it */ template_row = FindInTable(templates,name,0,FIND_NO_CASE); /* get the row of the template to del. */ DeleteFile(AddPaths(appdata,templates[template_row][1])); /* delete the preferences file */ templates[template_row][0] = ""; /* empty the name of the template */ templates[template_row][1] = ""; /* empty the path of the template */ rc = CSVWriteTable(templates,template_path); /* write the table back out */ if (IsError(rc)){ /* if the write failed */ MessageBox('x',DELETE_ERR,rc); /* display an error message */ return rc; /* return the error */ } /* */ current_template = GetSetting("Settings","current_template"); /* get the current template name */ if (current_template == name){ /* if we just deleted that one */ PutSetting("Settings","current_template",""); /* set the current template to nothing */ } /* */ num_templates = TextToInteger(GetSetting("Settings", /* get the number of active templates */ "num_templates")); /* */ num_templates = num_templates - 1; /* decrement it by one */ PutSetting("Settings","num_templates", /* write the number of templates back */ FormatString("%d",num_templates)); /* */ clean_blank_rows(); /* clean any blank rows out */ } /* */ return ERROR_NONE; /* return no error */ } /* */
The oddly-named function load_load loads our load template dialog with options. It’s called automatically by the DialogBox function and is run before the dialog is shown to the user. It gets the current template and reads our CSV template file. For each non-blank row in the CSV template file, it inserts a value into our menu_opts array. Then it uses the ComboBoxAddArray function to load the list into our dialog’s combo box control.
When the list is loaded, we use the ComboBoxSelectItem function to set the selected value as our active template.
/****************************************/ void load_load(){ /* load the load dialog */ /****************************************/ string appdata; /* application data folder */ string current_template; /* current active template */ string template_path; /* path to template CSV */ string templates[][]; /* contents of template CSV */ string menu_opts[]; /* menu options for load */ int num_opts; /* number of options in menu */ int ix; /* counter variable */ /* */ current_template = GetSetting("Settings","current_template"); /* get the currently active template */ appdata = GetApplicationDataFolder(); /* get the appdata folder */ template_path = AddPaths(appdata,PREFS_FILE); /* get the path to the CSV file */ if (IsFile(template_path)){ /* if the CSV file exists */ templates = CSVReadTable(template_path); /* read it */ num_opts = ArrayGetAxisDepth(templates); /* get the number of options on it */ for(ix=0; ix<num_opts; ix++){ /* for each option */ if (templates[ix][0]!=""){ /* if the row is not blank */ menu_opts[ix] = templates[ix][0]; /* set the menu option */ } /* */ } /* */ ComboBoxAddArray(TEMPLATE_OPTS,menu_opts); /* set the combo box values */ ComboBoxSelectItem(TEMPLATE_OPTS,current_template); /* set the selected val to current */ } /* */ } /* */
When the user presses the “OK” button on the load dialog, the load_validate function is called. If it returns true, then the dialog closes. If it returns false, it means the user made an invalid selection, and the dialog stays up so the user can select something else and try again. First, we get the selected item. If it’s blank, we display an error and return an error. Otherwise, we can read the CSV template file and build the path to our application settings file. The settings file is always named with a product name, then “Settings.ini”, so GoFiler Complete Settings.ini for example. We want this to work with all Novaworks products though, so instead of hard-coding the product name, we can just use the GetApplicationName function. From our CSV template file, we can get the filename for the template, and then use CopyFile to copy the template over the application settings file. If that was successful, we then run LoadPreferences to force the application to reload its preferences from its settings file, which we’ve just modified. Then we can change the active template to the one we just loaded with PutSetting and display a success message to the user.
/****************************************/ boolean load_validate(){ /* validate the load selection */ /****************************************/ string selected; /* selected template */ string appdata; /* appdata folder */ string template_path; /* path to CSV template file */ string templates[][]; /* data from templates file */ string product; /* product name (ex. GoFiler Complete) */ string old_template_fn; /* previous template filename */ string new_template_fn; /* new template filename */ int num_opts; /* number of available options */ int ix; /* counter variable */ int rc; /* result code */ /* */ selected = ComboBoxGetEditText(TEMPLATE_OPTS); /* get the selected value from combo box*/ if (selected == ""){ /* if nothing was selected */ MessageBox('x',NO_TEMPLATE_SELECT); /* display message */ return ERROR_EXIT; /* return with error */ } /* */ appdata = GetApplicationDataFolder(); /* get the appdata folder */ template_path = AddPaths(appdata,PREFS_FILE); /* get the path to the CSV file */ if (IsFile(template_path)){ /* if the CSV file exists */ templates = CSVReadTable(template_path); /* read the CSV file */ rc = GetLastError(); /* get the last error */ if (IsError(rc)){ /* if we cannot read the template file */ MessageBox('x',READ_TEMPLATE_ERR,rc); /* display an error */ return ERROR_EXIT; /* return with error */ } /* */ product = GetApplicationName(); /* get the application name */ old_template_fn = AddPaths(appdata,product+" Settings.ini"); /* build path to settings file */ ix = FindInTable(templates,selected,0,FIND_NO_CASE); /* get the index of the selected tmplt */ new_template_fn = templates[ix][1]; /* get the filename of the new tmplt */ new_template_fn = AddPaths(appdata,new_template_fn); /* build path to new template */ rc = CopyFile(new_template_fn,old_template_fn); /* copy new template over old one */ if (IsError(rc)){ /* if copy failed */ MessageBox('x',LOAD_ERR,rc); /* display error message */ return rc; /* return error */ } /* */ rc = LoadPreferences(); /* load the new preferences file */ if (IsError(rc)){ /* if the load failed */ MessageBox('x',LOAD_ERR,rc); /* display error message */ return rc; /* return error */ } /* */ PutSetting("Settings","current_template",selected); /* store new template selection */ MessageBox('i',SUCCESS_MSG,selected); /* display success message */ return ERROR_NONE; /* return no error */ } /* */ } /* */
Our save_load function is another load, called by our save dialog before it’s visible. This one just checks if we’re renaming a file. If so, the variable current_template is set to the name of the file we’re renaming. Otherwise it’s the name of the active template. Then we can use EditSetText to set that name into our dialog.
/****************************************/ void save_load(){ /* load the save function */ /****************************************/ string current_template; /* name of current template */ /* */ if (renaming == true){ /* if we're renaming not saving new */ current_template = old_name; /* current template is the old tplt name*/ } /* */ else{ /* else not renaming */ current_template = GetSetting("Settings","current_template"); /* get current template name */ } /* */ EditSetText(TEMPLATE_NAME,current_template); /* set the value into the dialog */ } /* */
The last function here is save_validate, which makes sure the name chosen by the user is valid, and doesn’t exist already in the CSV template file. It also creates the template, assuming the name is indeed valid. First, we get the name out of the dialog, and check it against our TEMPLATE_REGEX define with the function IsRegexMatch. If it’s not valid, we can just display an error and return with an error. If it’s valid, we convert it to a file name by stripping out the spaces, and appending “_preferences.ini” to it. Then we can read our CSV file, and use FindInTable to check to see if that file name already exists in our list. If so, we are definitely replacing an existing value, so we can set that flag to true. If we’re renaming, we need to immediately display an error and quit, because you can’t have two templates with the same name. If we’re saving a new one, we can ask the user if we want to overwrite. If he doesn’t press “Yes”, we can just exit.
/****************************************/ int save_validate(){ /* validate the save name dialog */ /****************************************/ string templates[][]; /* template CSV data */ string template_path; /* path to template CSV */ string new_template_nm; /* new template name */ string new_template_fn; /* new template filename */ string old_template_fn; /* old template filename */ string appdata; /* appdata folder */ string product; /* product name */ string current_template; /* currently selected template */ boolean replaced; /* true if replacing existing template */ int num_templates; /* number of available templates */ int old_template_pos; /* old template position in list */ int ix; /* counter index */ int rc; /* result code */ /* */ replaced = false; /* initialize replaced */ new_template_nm = EditGetText(TEMPLATE_NAME); /* get the name of the new template */ if (IsRegexMatch(new_template_nm,TEMPLATE_REGEX)==false){ /* if user entered invalid name */ MessageBox('x',INVALID_NAME_ERR); /* show error message */ return ERROR_EXIT; /* return error */ } /* */ new_template_fn=ConvertNoSpaces(new_template_nm)+"_preferences.ini";/* convert entered name to filename */ appdata = GetApplicationDataFolder(); /* get appdata folder */ template_path = AddPaths(appdata,PREFS_FILE); /* get path to CSV template file */ if (IsFile(template_path)){ /* if it's a valid file */ templates = CSVReadTable(template_path); /* read the template CSV file */ rc = GetLastError(); /* get the last error */ if (IsError(rc)){ /* if we failed to read template CSV */ MessageBox('x',READ_TEMPLATE_ERR,rc); /* display error message */ return rc; /* return a result code */ } /* */ ix = FindInTable(templates,new_template_fn,1,FIND_NO_CASE); /* see if tmplt with same fn exists */ if (ix >= 0){ /* if already exists */ replaced = true; /* set replaced flag to true */ if (renaming){ /* if we're renaming */ MessageBox('x',TEMPLATE_EXISTS_ERR_F,new_template_fn); /* display error */ return ERROR_EXIT; /* return */ } /* otherwise, continue */ rc = YesNoBox('q',TEMPLATE_EXISTS_ERR,new_template_fn); /* ask the user if they want to replace */ if (rc!=IDYES){ /* if the user didn't press yes */ return ERROR_EXIT; /* return error */ } /* */ } /* */ else{ /* if nothing with that filename exist */
If there wasn’t a template with the same name, we need to set the index to the end of the table so we insert a new row at the end of it. Next, we can check if we’re renaming an existing row. If so, we need to use CopyFile to make a new copy of our template with the new name, then run our delete routine to get rid of the old one. “Renaming” is a bit of a misnomer here I guess then, since we’re making a copy with a new name then deleting the old one. Then we can re-read our templates file, since it’s been changed by the delete function, and set our index to the depth of the table so we can insert our new row at the end of it. After that, we set our new values into our templates table, and if not renaming, we need to actually copy our current settings file to the new template location. Once it’s copied, we can check to see if we replaced an existing entry. If we didn’t and inserted a new row, we can increment the number of templates in our settings file. Finally, we can check if we renamed one more time, because if so we need to see if we renamed the active template file. If we did, we need to update the current template name. If we weren’t renaming something, we always need to update the current template name. Now we can just write our table back out, and it’s done!
ix = ArrayGetAxisDepth(templates); /* new index is size of table */ } /* */ } /* */ if (renaming){ /* if we're renaming */ CopyFile(AddPaths(appdata,ConvertNoSpaces(old_name)+"_preferences.ini"), AddPaths(appdata,ConvertNoSpaces(new_template_nm)+"_preferences.ini")); rc = delete(old_name); /* delete the old entry in the table */ templates = CSVReadTable(template_path); /* read the new CSV file back in */ ix = ArrayGetAxisDepth(templates); /* get the new number of templates */ if (IsError(rc)){ /* if the delete failed */ return rc; /* return the error */ } /* */ } /* */ templates[ix][0] = new_template_nm; /* store template name */ templates[ix][1] = new_template_fn; /* store template filename */ if (!renaming){ /* */ product = GetApplicationName(); /* get product name */ old_template_fn = AddPaths(appdata,product+" Settings.ini"); /* get path to settings file */ new_template_fn = AddPaths(appdata,new_template_fn); /* get path to new template file */ rc = CopyFile(old_template_fn, new_template_fn); /* make copy of current settings */ if (IsError(rc)){ /* if copy failed */ MessageBox('x',COPY_ERR,rc); /* display message */ return ERROR_EXIT; /* return error */ } /* */ } /* */ if (replaced==false){ /* only do this if didn't replace */ num_templates = TextToInteger( /* get number of available templates */ GetSetting("Settings","num_templates")); /* get number of available templates */ num_templates = num_templates + 1; /* increment it by one */ PutSetting("Settings","num_templates", /* store the number of templates */ FormatString("%d",num_templates)); /* */ } if (renaming){ /* if we're renaming a template */ current_template = GetSetting("Settings","current_template"); /* get the current template */ if (current_template == old_name || current_template == ""){ /* if we renamed the current template */ PutSetting("Settings","current_template",new_template_nm); /* store the new name of the template */ } /* */ } /* */ else{ /* if we're not renaming */ PutSetting("Settings","current_template",new_template_nm); /* set the current template name */ } /* */ CSVWriteTable(templates, template_path); /* write out the new CSV templates table*/ return ERROR_NONE; /* return no error */ }
Nothing in this script is overly complicated, but it still ended up being one of the larger scripts written in this blog. Whenever you have multiple functions interacting with multiple dialogs, it can get a bit verbose, but in the end you add a lot of functionality to GoFiler that it didn’t have natively. Of course, it can be expanded on even further, instead of just switching out the settings files it could also swap out template files to give entirely different looks to proof files depending on the template selected. It can be modified to store these template files in a programmable folder, maybe one that can be shared, instead of the user’s appdata directory. In the end, we need to be careful that we don’t spend too much time writing things that would be “cool” but aren’t really needed, because there’s really no end to the improvements you can make, and you don’t want to spend forever working on something.
Here is the full script in its entirety below. Please note for this to work the script file MUST be named “PreferencesSwitcher.ms”.
/* PreferencesSwitcher.ms * * Author: Steven Horowitz * * Rev 01 SCH 4/04/18 * * Notes: Allows a user to save and switch Preferences profiles. */ /************************************************/ /* Defined Error / Warning Messages */ /************************************************/ #define PREFS_FILE "preference_templates.csv" #define TEMPLATE_REGEX "^[a-zA-Z\\d\\s]+$" #define READ_TEMPLATE_ERR "Cannot read template file, error code %0x" #define INVALID_NAME_ERR "Template names must be only letters, numbers, and spaces." #define TEMPLATE_EXISTS_ERR "Template with the name \"%s\" already exists. Overwrite?" #define TEMPLATE_EXISTS_ERR_F "Template with the name \"%s\" already exists." #define NO_TEMPLATES_EXIST_ERR "Cannot load or edit templates, no templates exist." #define RENAME_ERR "Cannot rename template, error code %0x." #define COPY_ERR "Cannot save new template, error %0x" #define LOAD_ERR "Cannot load existing template, error %0x" #define NO_TEMPLATE_SELECT "Must select a valid template before continuing." #define SUCCESS_MSG "Loaded preferences template \"%s\" successfully." #define DELETE_MSG "This will delete the preference template \"%s\". Continue?" #define DELETE_ERR "Cannot delete %s, error: %0x" #define FILE_WARNING "Submission will be filed by CIK %s. Continue?" /************************************************/ /* Defined Settings */ /************************************************/ #define ENABLE_WARN true /* true to warn on filing what the profile is */ /************************************************/ /* Function Signatures */ /************************************************/ void setup(); /* set up the hooks */ void run_save(int f_id, string mode); /* run the save template script */ void run_load(int f_id, string mode); /* run the load template script */ void run_mod(int f_id, string mode); /* run the modify template script */ int run_warnings(int f_id, string mode); /* warn a user about what CIK is logging in */ void clean_blank_rows(); /* clear blank rows out of our CSV file */ int rename(string name); /* rename a template */ int delete(string name); /* delete a template */ /************************************************/ /* Global Variables */ /************************************************/ boolean renaming; /* true if renaming a file */ string old_name; /* the previous name in a renamed file */ /****************************************/ void setup() { /* Called from Application Startup */ /****************************************/ string fn; /* file name */ string item[10]; /* menu item array */ string settings; /* the settings file location */ string gf_folder; /* gofiler execution folder */ /* */ gf_folder = GetApplicationExecuteFolder(); /* get the execution folder */ settings =AddPaths(gf_folder,"Templates\\DefaultSettings.ini"); /* path to the default settings file */ if(IsFile(settings)==true){ /* if default settings exist */ return ERROR_NONE; /* don't use this script. */ } /* */ /* */ item["Code"] = "SAVE_PREFERENCES"; /* set hook code */ item["Description"] = "Save the current set of preferences"; /* set hook description */ item["MenuText"] = "Save Preferences"; /* set menu text */ MenuAddFunction(item); /* add menu item to menu */ fn = GetScriptFilename(); /* get the filename of the script */ MenuSetHook("SAVE_PREFERENCES", fn, "run_save"); /* set the hook */ /* */ item["Code"] = "LOAD_PREFERENCES"; /* set hook code */ item["Description"] = "Load a new set of preferences."; /* set hook description */ item["MenuText"] = "Load Preferences"; /* set menu text */ MenuAddFunction(item); /* add menu function */ MenuSetHook("LOAD_PREFERENCES", fn, "run_load"); /* set the hook */ /* */ item["Code"] = "MODIFY_PREFERENCES"; /* set the hook code */ item["Description"] = "Edit or delete saved preferences."; /* set the hook description */ item["MenuText"] = "Modify Preferences"; /* set the menu text */ MenuAddFunction(item); /* add to menu */ MenuSetHook("MODIFY_PREFERENCES", fn, "run_mod"); /* set the hook to menu item */ /* */ if (ENABLE_WARN){ /* if warnings are enabled */ MenuSetHook("EDGAR_SUBMIT_TEST", fn, "run_warn"); /* add the warning */ MenuSetHook("EDGAR_SUBMIT_LIVE", fn, "run_warn"); /* add the warning */ MenuSetHook("NSS_SUBMIT_DELAY", fn, "run_warn"); /* add the warning */ MenuSetHook("EDGAR_SUBMIT_TEST_AGENT", fn, "run_warn"); /* add the warning */ } /* */ } /* */ /****************************************/ int run_warn(int f_id, string mode){ /* run the warnings */ /****************************************/ int rc; /* result code */ string appdata; /* appdata folder location */ /* */ if (mode!="preprocess"){ /* if not in preprocess */ return; /* exit */ } /* */ appdata = GetApplicationDataFolder(); /* get the appdata folder */ if (IsFile(AddPaths(appdata,"PreferencesSwitcher.ini"))==false){ /* if it's not a file */ return; /* script not in use, so return */ } /* otherwise, script in use, so cont. */ rc = YesNoBox('i',FILE_WARNING,EDGARGetLoginCIK()); /* display warning */ if (rc!=IDYES){ /* if user doesn't press yes */ return ERROR_EXIT; /* abort filing process */ } /* */ } /* */ /****************************************/ void clean_blank_rows(){ /* clean up blank rows in prefs CSV */ /****************************************/ string file; /* file contents */ string appdata; /* appdata folder */ string filename; /* path to file */ /* */ appdata = GetApplicationDataFolder(); /* get the appdata folder location */ filename = AddPaths(appdata,PREFS_FILE); /* get path to the file */ if (IsFile(filename)){ /* if the file exists */ file = FileToString(filename); /* get the contents of the file */ file = ReplaceInString(file,"\"\",\"\"\r",""); /* remove blank rows */ StringToFile(file,filename); /* write the contents back out */ } /* */ } /* */ /****************************************/ void main(){ /* main function */ /****************************************/ setup(); /* run setup */ } /* */ /****************************************/ void run_save(int f_id, string mode){ /* run the save function */ /****************************************/ if (mode != "preprocess"){ /* if not preprocess */ return; /* bail out */ } /* */ renaming = false; /* set renaming flag to false */ DialogBox(PREFERENCE_TEMPLATES, "save_"); /* enter the save dialog */ } /* */ /****************************************/ void run_load(int f_id, string mode){ /* run the load function */ /****************************************/ string num_templates; /* number of available templates */ /* */ if (mode != "preprocess"){ /* if not preprocess, bail out */ return; /* return */ } /* */ /* */ num_templates = GetSetting("Settings","num_templates"); /* get the number of templates in use */ if (num_templates == "" || num_templates =="0"){ /* if there are no templates */ MessageBox('x',NO_TEMPLATES_EXIST_ERR); /* display error */ return; /* return */ } /* */ DialogBox(CHANGE_PREFS,"load_"); /* enter the load dialog */ } /* */ /****************************************/ void run_mod(int f_id, string mode){ /* run the modify function */ /****************************************/ string num_templates; /* number of templates */ /* */ if (mode != "preprocess"){ /* if not preprocess */ return; /* bail out */ } /* */ /* */ num_templates = GetSetting("Settings","num_templates"); /* get the number of templates */ if (num_templates == "" || num_templates =="0"){ /* if there are no templates */ MessageBox('x',NO_TEMPLATES_EXIST_ERR); /* display error */ return; /* return */ } /* */ DialogBox(MANAGE_TEMPLATES_DLG,"mod_"); /* enter the modify dialog */ } /* */ /****************************************/ void mod_load(){ /* load the modify dialog contents */ /****************************************/ string templates[][]; /* templates CSV file contents */ string template_path; /* the path to the template CSV file */ string appdata; /* application data folder */ int ix; /* counter variable */ int num_templates; /* number of templates */ /* */ DataControlResetContent(TEMPLATE_LIST); /* reset contents of the dialog */ appdata = GetApplicationDataFolder(); /* get the appdata folder */ template_path = AddPaths(appdata,PREFS_FILE); /* get the path to the template CSV */ if (IsFile(template_path)){ /* if the file exists */ templates = CSVReadTable(template_path); /* read it's contents */ DataControlSetColumnHeadings(TEMPLATE_LIST,"Template Name"); /* set the heading for the data control */ DataControlSetColumnPositions(TEMPLATE_LIST, 167); /* set the width of the heading */ num_templates = ArrayGetAxisDepth(templates); /* get the number of templates */ for(ix=0;ix<num_templates;ix++){ /* for each template in the file */ if (templates[ix][0]!=""){ /* if the template isn't blank */ DataControlInsertString(TEMPLATE_LIST,ix,templates[ix][0]); /* add it to the dialog */ } /* */ } /* */ } /* */ } /* */ /****************************************/ void mod_action(int c_id, int action){ /* action on the modify dialog */ /****************************************/ string selected_nm; /* selected name */ int selected; /* selected index value */ string data[][]; /* content of the dialog's list */ int rc; /* result code */ /* */ if (c_id != TEMPLATE_RENAME && c_id != TEMPLATE_DELETE){ /* if not one of our two buttons */ return; /* return */ } /* */ /* */ selected = DataControlGetRowSelection(TEMPLATE_LIST); /* get the selected item from the list */ if(selected < 0){ /* if there no selection */ MessageBox('x',NO_TEMPLATE_SELECT); /* display error */ return; /* return */ } /* */ /* */ data = DataControlGetTable(TEMPLATE_LIST); /* get the data from the list */ selected_nm = data[selected][0]; /* get the name of the selected row */ if (c_id == TEMPLATE_RENAME){ /* if rename was pressed */ rc = rename(selected_nm); /* run the rename function */ if (IsError(rc)==false){ /* if rename didn't return an error */ mod_load(); /* reload the list */ } /* */ return; /* return */ } /* */ if (c_id == TEMPLATE_DELETE){ /* if delete was pressed */ rc = delete(selected_nm); /* run the delete function */ if (IsError(rc)==false){ /* if delete didn't return an error */ mod_load(); /* reload the list */ } /* */ return; /* return */ } /* */ } /* */ /****************************************/ int rename(string name){ /* rename a template */ /****************************************/ int rc; /* result code */ /* */ old_name = name; /* store the previous name */ renaming = true; /* set rename flag for save function */ rc = DialogBox(PREFERENCE_TEMPLATES, "save_"); /* enter the save dialog */ if (IsError(rc) && rc!=ERROR_CANCEL){ /* if it was an error other than cancel */ MessageBox('x',RENAME_ERR,rc); /* display error */ return rc; /* return the error */ } /* */ return ERROR_NONE; /* return without error */ } /* */ /****************************************/ int delete(string name){ /* delete a template */ /****************************************/ int rc; /* result code */ string appdata; /* appdata folder */ string template_path; /* path to the template CSV file */ string templates[][]; /* contents of template CSV file */ string current_template; /* currently active template */ int template_row; /* id of the row in the CSV */ int num_templates; /* number of templates */ /* */ if (renaming){ /* if renaming the template */ rc = IDYES; /* assume yes to dialog */ } /* */ else{ /* if not in the middle of a rename */ rc = YesNoBox('q',DELETE_MSG,name); /* ask to confirm delete */ } /* */ if (rc!=IDYES){ /* if the user didn't press yes */ return ERROR_EXIT; /* exit with error */ } /* */ appdata = GetApplicationDataFolder(); /* get the application data area */ template_path = AddPaths(appdata,PREFS_FILE); /* get the path to the template CSV */ if (IsFile(template_path)){ /* if the file exists */ templates = CSVReadTable(template_path); /* read it */ template_row = FindInTable(templates,name,0,FIND_NO_CASE); /* get the row of the template to del. */ DeleteFile(AddPaths(appdata,templates[template_row][1])); /* delete the preferences file */ templates[template_row][0] = ""; /* empty the name of the template */ templates[template_row][1] = ""; /* empty the path of the template */ rc = CSVWriteTable(templates,template_path); /* write the table back out */ if (IsError(rc)){ /* if the write failed */ MessageBox('x',DELETE_ERR,rc); /* display an error message */ return rc; /* return the error */ } /* */ current_template = GetSetting("Settings","current_template"); /* get the active template name */ if (current_template == name){ /* if we just deleted that one */ PutSetting("Settings","current_template",""); /* set the current template to nothing */ } /* */ num_templates = TextToInteger(GetSetting("Settings", /* get the number of active templates */ "num_templates")); /* */ num_templates = num_templates - 1; /* decrement it by one */ PutSetting("Settings","num_templates", /* write the number of templates back */ FormatString("%d",num_templates)); /* */ clean_blank_rows(); /* clean any blank rows out */ } /* */ return ERROR_NONE; /* return no error */ } /* */ /****************************************/ void load_load(){ /* load the load dialog */ /****************************************/ string appdata; /* application data folder */ string current_template; /* current active template */ string template_path; /* path to template CSV */ string templates[][]; /* contents of template CSV */ string menu_opts[]; /* menu options for load */ int num_opts; /* number of options in menu */ int ix; /* counter variable */ /* */ current_template = GetSetting("Settings","current_template"); /* get the currently active template */ appdata = GetApplicationDataFolder(); /* get the appdata folder */ template_path = AddPaths(appdata,PREFS_FILE); /* get the path to the CSV file */ if (IsFile(template_path)){ /* if the CSV file exists */ templates = CSVReadTable(template_path); /* read it */ num_opts = ArrayGetAxisDepth(templates); /* get the number of options on it */ for(ix=0; ix<num_opts; ix++){ /* for each option */ if (templates[ix][0]!=""){ /* if the row is not blank */ menu_opts[ix] = templates[ix][0]; /* set the menu option */ } /* */ } /* */ ComboBoxAddArray(TEMPLATE_OPTS,menu_opts); /* set the combo box values */ ComboBoxSelectItem(TEMPLATE_OPTS,current_template); /* set the selected val to current */ } /* */ } /* */ /****************************************/ boolean load_validate(){ /* validate the load selection */ /****************************************/ string selected; /* selected template */ string appdata; /* appdata folder */ string template_path; /* path to CSV template file */ string templates[][]; /* data from templates file */ string product; /* product name (ex. GoFiler Complete) */ string old_template_fn; /* previous template filename */ string new_template_fn; /* new template filename */ int num_opts; /* number of available options */ int ix; /* counter variable */ int rc; /* result code */ /* */ selected = ComboBoxGetEditText(TEMPLATE_OPTS); /* get the selected value from combo box*/ if (selected == ""){ /* if nothing was selected */ MessageBox('x',NO_TEMPLATE_SELECT); /* display message */ return ERROR_EXIT; /* return with error */ } /* */ appdata = GetApplicationDataFolder(); /* get the appdata folder */ template_path = AddPaths(appdata,PREFS_FILE); /* get the path to the CSV file */ if (IsFile(template_path)){ /* if the CSV file exists */ templates = CSVReadTable(template_path); /* read the CSV file */ rc = GetLastError(); /* get the last error */ if (IsError(rc)){ /* if we cannot read the template file */ MessageBox('x',READ_TEMPLATE_ERR,rc); /* display an error */ return ERROR_EXIT; /* return with error */ } /* */ product = GetApplicationName(); /* get the application name */ old_template_fn = AddPaths(appdata,product+" Settings.ini"); /* build path to settings file */ ix = FindInTable(templates,selected,0,FIND_NO_CASE); /* get the index of the selected tmplt */ new_template_fn = templates[ix][1]; /* get the filename of the new tmplt */ new_template_fn = AddPaths(appdata,new_template_fn); /* build path to new template */ rc = CopyFile(new_template_fn,old_template_fn); /* copy new template over old one */ if (IsError(rc)){ /* if copy failed */ MessageBox('x',LOAD_ERR,rc); /* display error message */ return rc; /* return error */ } /* */ rc = LoadPreferences(); /* load the new preferences file */ if (IsError(rc)){ /* if the load failed */ MessageBox('x',LOAD_ERR,rc); /* display error message */ return rc; /* return error */ } /* */ PutSetting("Settings","current_template",selected); /* store new template selection */ MessageBox('i',SUCCESS_MSG,selected); /* display success message */ return ERROR_NONE; /* return no error */ } /* */ } /* */ /****************************************/ void save_load(){ /* load the save function */ /****************************************/ string current_template; /* name of current template */ /* */ if (renaming == true){ /* if we're renaming not saving new */ current_template = old_name; /* current template is the old tplt name*/ } /* */ else{ /* else not renaming */ current_template = GetSetting("Settings","current_template"); /* get current template name */ } /* */ EditSetText(TEMPLATE_NAME,current_template); /* set the value into the dialog */ } /* */ /****************************************/ /* */ int save_validate(){ /* validate the save name dialog */ /****************************************/ string templates[][]; /* template CSV data */ string template_path; /* path to template CSV */ string new_template_nm; /* new template name */ string new_template_fn; /* new template filename */ string old_template_fn; /* old template filename */ string appdata; /* appdata folder */ string product; /* product name */ string current_template; /* currently selected template */ boolean replaced; /* true if replacing existing template */ int num_templates; /* number of available templates */ int old_template_pos; /* old template position in list */ int ix; /* counter index */ int rc; /* result code */ /* */ replaced = false; /* initialize replaced */ new_template_nm = EditGetText(TEMPLATE_NAME); /* get the name of the new template */ if (IsRegexMatch(new_template_nm,TEMPLATE_REGEX)==false){ /* if user entered invalid name */ MessageBox('x',INVALID_NAME_ERR); /* show error message */ return ERROR_EXIT; /* return error */ } /* */ new_template_fn=ConvertNoSpaces(new_template_nm)+"_preferences.ini";/* convert entered name to filename */ appdata = GetApplicationDataFolder(); /* get appdata folder */ template_path = AddPaths(appdata,PREFS_FILE); /* get path to CSV template file */ if (IsFile(template_path)){ /* if it's a valid file */ templates = CSVReadTable(template_path); /* read the template CSV file */ rc = GetLastError(); /* get the last error */ if (IsError(rc)){ /* if we failed to read template CSV */ MessageBox('x',READ_TEMPLATE_ERR,rc); /* display error message */ return rc; /* return a result code */ } /* */ ix = FindInTable(templates,new_template_fn,1,FIND_NO_CASE); /* see if tmplt with same fn exists */ if (ix >= 0){ /* if already exists */ replaced = true; /* set replaced flag to true */ if (renaming){ /* if we're renaming */ MessageBox('x',TEMPLATE_EXISTS_ERR_F,new_template_fn); /* display error */ return ERROR_EXIT; /* return */ } /* otherwise, continue */ rc = YesNoBox('q',TEMPLATE_EXISTS_ERR,new_template_fn); /* ask the user if they want to replace */ if (rc!=IDYES){ /* if the user didn't press yes */ return ERROR_EXIT; /* return error */ } /* */ } /* */ else{ /* if nothing with that filename exist */ ix = ArrayGetAxisDepth(templates); /* new index is size of table */ } /* */ } /* */ if (renaming){ /* if we're renaming */ CopyFile(AddPaths(appdata,ConvertNoSpaces(old_name)+"_preferences.ini"), AddPaths(appdata,ConvertNoSpaces(new_template_nm)+"_preferences.ini")); rc = delete(old_name); /* delete the old entry in the table */ templates = CSVReadTable(template_path); /* read the new CSV file back in */ ix = ArrayGetAxisDepth(templates); /* get the new number of templates */ if (IsError(rc)){ /* if the delete failed */ return rc; /* return the error */ } /* */ } /* */ templates[ix][0] = new_template_nm; /* store template name */ templates[ix][1] = new_template_fn; /* store template filename */ if (!renaming){ /* */ product = GetApplicationName(); /* get product name */ old_template_fn = AddPaths(appdata,product+" Settings.ini"); /* get path to settings file */ new_template_fn = AddPaths(appdata,new_template_fn); /* get path to new template file */ rc = CopyFile(old_template_fn, new_template_fn); /* make copy of current settings */ if (IsError(rc)){ /* if copy failed */ MessageBox('x',COPY_ERR,rc); /* display message */ return ERROR_EXIT; /* return error */ } /* */ } /* */ if (replaced==false){ /* only do this if didn't replace */ num_templates = TextToInteger( /* get number of available templates */ GetSetting("Settings","num_templates")); /* get number of available templates */ num_templates = num_templates + 1; /* increment it by one */ PutSetting("Settings","num_templates", /* store the number of templates */ FormatString("%d",num_templates)); /* */ } if (renaming){ /* if we're renaming a template */ current_template = GetSetting("Settings","current_template"); /* get the current template */ if (current_template == old_name || current_template == ""){ /* if we renamed the current template */ PutSetting("Settings","current_template",new_template_nm); /* store the new name of the template */ } /* */ } /* */ else{ /* if we're not renaming */ PutSetting("Settings","current_template",new_template_nm); /* set the current template name */ } /* */ CSVWriteTable(templates, template_path); /* write out the new CSV templates table*/ return ERROR_NONE; /* return no error */ } /************************************************/ /* dialog controls */ /************************************************/ #beginresource /****************************************/ /* save template dialog */ /****************************************/ #define PREFERENCE_TEMPLATES 101 #define TEMPLATE_PROPERTIES 102 #define TEMPLATE_NAME 103 PREFERENCE_TEMPLATES DIALOGEX 0, 0, 240, 66 EXSTYLE WS_EX_DLGMODALFRAME STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "Preference Template Properties" FONT 8, "MS Sans Serif" { CONTROL "OK", IDOK, "BUTTON", BS_PUSHBUTTON | BS_CENTER | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 132, 50, 50, 14 CONTROL "Cancel", IDCANCEL, "BUTTON", BS_PUSHBUTTON | BS_CENTER | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 187, 50, 50, 14 CONTROL "Name:", -1, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 14, 25, 40, 13, 0 CONTROL "Template Properties:", -1, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 10, 8, 86, 13, 0 CONTROL "Frame1", -1, "static", SS_ETCHEDFRAME | WS_CHILD | WS_VISIBLE, 84, 12, 146, 1, 0 CONTROL "", TEMPLATE_NAME, "edit", ES_LEFT | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 53, 25, 172, 12, 0 } /****************************************/ /* load template dialog */ /****************************************/ #define CHANGE_PREFS 100 #define NEW_TEMPLATE_NAME 101 #define TEMPLATE_OPTS 102 CHANGE_PREFS DIALOGEX 0, 0, 182, 55 EXSTYLE WS_EX_DLGMODALFRAME STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "Change Preferences Template" FONT 8, "MS Sans Serif" { CONTROL "OK", IDOK, "BUTTON", BS_PUSHBUTTON | BS_CENTER | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 64, 36, 50, 14 CONTROL "Cancel", IDCANCEL, "BUTTON", BS_PUSHBUTTON | BS_CENTER | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 124, 36, 50, 14 CONTROL "", TEMPLATE_OPTS, "combobox", CBS_DROPDOWN | CBS_SORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 40, 12, 136, 17, 0 CONTROL "Template:", -1, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 5, 14, 32, 9, 0 } /****************************************/ /* modify template dialog */ /****************************************/ #define MANAGE_TEMPLATES_DLG 200 #define TEMPLATE_LIST 201 #define TEMPLATE_DELETE 202 #define TEMPLATE_RENAME 203 MANAGE_TEMPLATES_DLG DIALOGEX 0, 0, 244, 143 EXSTYLE WS_EX_DLGMODALFRAME STYLE DS_3DLOOK | DS_MODALFRAME | DS_SETFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU CAPTION "Manage Preference Templates" FONT 8, "MS Shell Dlg" { CONTROL "", TEMPLATE_LIST, "data_control", 0x50A10003, 13, 6, 167, 106, 0x00000000 CONTROL "&Delete", TEMPLATE_DELETE, "button", BS_CENTER, 183, 7, 50, 14, WS_EX_LEFT CONTROL "&Rename", TEMPLATE_RENAME, "button", BS_CENTER, 183, 24, 50, 14, WS_EX_LEFT CONTROL "", -1, "static", SS_ETCHEDFRAME, 6, 118, 234, 1, WS_EX_LEFT CONTROL "Done", IDOK, "button", BS_PUSHBUTTON |BS_CENTER, 183, 123, 50, 14, WS_EX_LEFT } #endresource
Steven Horowitz has been working for Novaworks for over five years as a technical expert with a focus on EDGAR HTML and XBRL. Since the creation of the Legato language in 2015, Steven has been developing scripts to improve the GoFiler user experience. He is currently working toward a Bachelor of Sciences in Software Engineering at RIT and MCC. |
Additional Resources
Legato Script Developers LinkedIn Group
Primer: An Introduction to Legato