Recipe dialog working, data being saved and loaded from projects.

This commit is contained in:
Scott Duensing 2023-04-19 19:38:04 -05:00
parent 73ee8388de
commit f513dc3893
4 changed files with 178 additions and 26 deletions

View file

@ -27,6 +27,12 @@
#include "../thirdparty/stb_ds.h"
typedef struct StringHashS {
char *key;
char *value;
} StringHashT;
#define ARRFREE(a) do { if (a != NULL) { arrfree(a); } break; } while(1)

View file

@ -22,6 +22,7 @@
#pragma clang diagnostic push
#pragma ide diagnostic ignored "cppcoreguidelines-narrowing-conversions"
#pragma ide diagnostic ignored "cert-err34-c" // atoi warnings
#include "common.h"
@ -68,6 +69,7 @@ typedef struct TargetS {
typedef struct ProjectDataS {
WindowDataT windowData;
GtkWidget *treeProject;
StringHashT **recipes;
char *configName;
char *buildHost;
int buildHTTPPort;
@ -93,19 +95,23 @@ static SectionDataT _sectionData[] = {
{ "Vector", "*.vic" },
{ "Sound", "*.snd" },
{ "Music", "*.mod" },
{ "Raw Data", NULL },
{ "Cooked Data", NULL },
{ NULL, NULL }
{ "Raw Data", NULL },
{ "Cooked Data", "*.dat" },
{ NULL, NULL }
};
#define BUILD_SETTINGS_RESPONSE_TEST 1
static void addToRecipeData(ProjectDataT *self, char *key, char *value);
static void addToTree(ProjectDataT *self, char *filename);
EVENT void buildTargetClicked(GtkButton *widget, gpointer userData);
EVENT void btnEditRecipeClicked(GtkButton *widget, gpointer userData);
EVENT void btnNewRecipeClicked(GtkButton *widget, gpointer userData);
static void clearRecipeData(ProjectDataT *self);
static void dialogCookOptions(char *filename, ProjectDataT *self);
static int findRecipeData(ProjectDataT *self, char *key);
static void loadConfig(ProjectDataT *self);
static void loadProject(ProjectDataT *self);
EVENT void menuProjectFileNew(GtkWidget *object, gpointer userData);
@ -128,6 +134,20 @@ EVENT gboolean winProjectClose(GtkWidget *object, gpointer userData);
static void winProjectDelete(gpointer userData);
static void addToRecipeData(ProjectDataT *self, char *key, char *value) {
int i;
StringHashT *s;
i = findRecipeData(self, key);
if (i >= 0) arrdel(self->recipes, i);
s = NEW(StringHashT);
s->key = strdup(key);
s->value = strdup(value);
arrput(self->recipes, s);
}
static void addToTree(ProjectDataT *self, char *filename) {
ProjectSectionTypeT section;
char *temp = NULL;
@ -176,8 +196,6 @@ static void addToTree(ProjectDataT *self, char *filename) {
gtk_tree_store_set(GTK_TREE_STORE(model), &child, COL_FILENAME, filename, -1);
DEL(temp);
//***TODO*** Need to store extra RAW data somewhere.
gtk_tree_view_expand_all(GTK_TREE_VIEW(self->treeProject));
}
}
@ -190,6 +208,20 @@ EVENT void buildTargetClicked(GtkButton *widget, gpointer userData) {
}
EVENT void btnEditRecipeClicked(GtkButton *widget, gpointer userData) {
ProjectDataT *self = (ProjectDataT *)userData;
char *file = NULL;
(void)widget;
file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(self->tempWidget));
if (utilFileExists(file)) {
//***TODO*** Text Editor
}
DEL(file);
}
EVENT void btnNewRecipeClicked(GtkButton *widget, gpointer userData) {
ProjectDataT *self = (ProjectDataT *)userData;
char *newFile = NULL;
@ -215,6 +247,17 @@ EVENT void btnNewRecipeClicked(GtkButton *widget, gpointer userData) {
}
static void clearRecipeData(ProjectDataT *self) {
// Clear recipe data.
while (arrlen(self->recipes) > 0) {
DEL(self->recipes[0]->key);
DEL(self->recipes[0]->value);
arrdel(self->recipes, 0);
}
ARRFREE(self->recipes);
}
static void dialogCookOptions(char *filename, ProjectDataT *self) {
GtkWidget *dialogCookSettings;
GtkWidget *lblRaw;
@ -223,9 +266,13 @@ static void dialogCookOptions(char *filename, ProjectDataT *self) {
GtkWidget *lblCooked;
GtkWidget *btnCancel;
GtkWidget *btnOkay;
int result = 0;
int original;
int result;
int i;
char *raw = NULL;
char *cooked = NULL;
char *temp = NULL;
char *path = NULL;
char *widgetNames[] = {
"dialogCookSettings",
"lblRaw",
@ -253,21 +300,64 @@ static void dialogCookOptions(char *filename, ProjectDataT *self) {
cooked = utilFileRemoveExtension(raw);
strcat(cooked, ".dat");
gtk_label_set_text(GTK_LABEL(lblCooked), cooked);
DEL(cooked);
DEL(raw);
self->tempWidget = fileRecipe;
result = gtk_dialog_run(GTK_DIALOG(dialogCookSettings));
if (result == GTK_RESPONSE_OK) {
// Find path of project file.
path = strdup(self->windowData.filename);
cwk_path_get_dirname(path, (size_t *)&i);
if (i > 0) path[i] = 0;
original = findRecipeData(self, raw);
if (original >= 0) {
cwk_path_change_basename(self->windowData.filename, self->recipes[original]->value, __utilFilenameBuffer, sizeof(__utilFilenameBuffer));
gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(fileRecipe), __utilFilenameBuffer);
}
result = gtk_dialog_run(GTK_DIALOG(dialogCookSettings));
if (result == GTK_RESPONSE_OK) {
temp = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fileRecipe));
if (temp != NULL) {
// Convert to relative path.
cwk_path_get_relative(path, temp, __utilFilenameBuffer, sizeof(__utilFilenameBuffer));
if (__utilFilenameBuffer[0] != 0) {
DEL(temp);
temp = strdup(__utilFilenameBuffer);
}
// Did the recipe change?
if (!((original >= 0) && (strcmp(self->recipes[original]->value, temp) == 0))) {
addToTree(self, cooked);
addToRecipeData(self, raw, temp);
utilSetDirty((WindowDataT *)self, TRUE);
}
DEL(temp);
}
}
DEL(path);
DEL(cooked);
DEL(raw);
self->tempWidget = NULL;
gtk_widget_destroy(dialogCookSettings);
}
static int findRecipeData(ProjectDataT *self, char *key) {
int i;
int result = -1;
for (i=0; i<arrlen(self->recipes); i++) {
if (strcmp(self->recipes[i]->key, key) == 0) {
result = i;
break;
}
}
return result;
}
static void loadConfig(ProjectDataT *self) {
FILE *in = NULL;
char *line = NULL;
@ -337,14 +427,16 @@ static void loadConfig(ProjectDataT *self) {
static void loadProject(ProjectDataT *self) {
FILE *in = NULL;
char *line = NULL;
size_t len = 0;
char *c = NULL;
TargetT *t = NULL;
FILE *in = NULL;
char *line = NULL;
size_t len = 0;
char *c = NULL;
TargetT *t = NULL;
int i;
int j;
char *path = NULL;
char *path = NULL;
char *raw = NULL;
char *cooked = NULL;
in = fopen(self->windowData.filename, "rt");
if (in != NULL) {
@ -354,16 +446,17 @@ static void loadProject(ProjectDataT *self) {
self->targets[i]->archs[j]->selected = FALSE;
}
}
// Find path of config file.
// Find path of project file.
path = strdup(self->windowData.filename);
cwk_path_get_dirname(path, &i);
cwk_path_get_dirname(path, (size_t *)&i);
if (i > 0) path[i] = 0;
// Load config.
// Load project.
utilEnsureBufferSize((unsigned char **)&line, (int *)&len, 1024); // Not technically needed, but fixes a pointer warning from memmaker.
while (getline(&line, &len, in) != -1) {
if (strlen(line) > 0) line[strlen(line) - 1] = 0;
c = utilGetToken(line, " ", "\"", "\"");
utilDequote(c);
// Is this a 'source' line?
if (strcasecmp(c, "source") == 0) {
c = utilGetToken(NULL, " ", "\"", "\"");
@ -374,13 +467,15 @@ static void loadProject(ProjectDataT *self) {
} else {
addToTree(self, __utilFilenameBuffer);
}
continue;
}
// Is this a 'target' line?
if (strcasecmp(c, "target") == 0) {
c = utilGetToken(NULL, " ", "\"", "\"");
utilDequote(c);
// See if we know about this target.
for (i=0; i<self->targets; i++) {
for (i=0; i < arrlen(self->targets); i++) {
if (strcasecmp(self->targets[i]->name, c) == 0) {
t = self->targets[i];
// We know this target. Iterate over specified arches and turn them on if known.
@ -399,7 +494,31 @@ static void loadProject(ProjectDataT *self) {
break;
}
}
continue;
}
// Is this a 'recipe' line?
if (strcasecmp(c, "recipe") == 0) {
c = utilGetToken(NULL, " ", "\"", "\"");
utilDequote(c);
raw = strdup(c);
cooked = utilFileRemoveExtension(raw);
strcat(cooked, ".dat");
addToTree(self, cooked);
c = utilGetToken(NULL, " ", "\"", "\"");
utilDequote(c);
cwk_path_get_relative(path, c, __utilFilenameBuffer, sizeof(__utilFilenameBuffer));
if (__utilFilenameBuffer[0] == 0) {
addToRecipeData(self, raw, c);
debug("Writing Recipe [%s] = [%s]\n", raw, c);
} else {
addToRecipeData(self, raw, __utilFilenameBuffer);
debug("Writing Recipe [%s] = [%s]\n", raw, __utilFilenameBuffer);
}
DEL(cooked);
DEL(raw);
}
}
fclose(in);
DEL(line);
@ -445,6 +564,8 @@ EVENT void menuProjectFileNew(GtkWidget *object, gpointer userData) {
}
}
clearRecipeData(self);
// Nuke filename & mark clean.
DEL(self->windowData.filename);
utilSetDirty(&self->windowData, FALSE);
@ -493,7 +614,6 @@ EVENT void menuProjectFileSave(GtkWidget *object, gpointer userData) {
do {
if (gtk_tree_model_iter_children(model, &child, &iter)) {
do {
//***TODO*** For RAW we need to store function name somewhere.
gtk_tree_model_get(model, &child, COL_FILENAME, &temp, -1);
fprintf(out, "source \"%s\"\n", temp);
DEL(temp); // This generates an unknown pointer warning in memwatch. Pretty sure it's bogus.
@ -516,6 +636,10 @@ EVENT void menuProjectFileSave(GtkWidget *object, gpointer userData) {
}
if (archWritten == TRUE) fprintf(out, "\n");
}
// Write out any data file recipes.
for (i=0; i<arrlen(self->recipes); i++) {
fprintf(out, "recipe \"%s\" \"%s\"\n", self->recipes[i]->key, self->recipes[i]->value);
}
// Close file.
fclose(out);
// We're clean now.
@ -566,7 +690,7 @@ EVENT void menuProjectProjectAdd(GtkWidget *object, gpointer userData) {
if (self->windowData.filename != NULL) {
path = strdup(self->windowData.filename);
cwk_path_get_dirname(path, &x);
cwk_path_get_dirname(path, (size_t *)&x);
if (x > 0) path[x] = 0;
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),path);
}
@ -608,6 +732,8 @@ EVENT void menuProjectProjectRemove(GtkWidget *object, gpointer userData) {
GtkTreeModel *model;
GtkTreeIter iter;
(void)object;
// Is anything selected?
if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
// Are we on a child item?
@ -756,6 +882,8 @@ EVENT void menuProjectBuildTargets(GtkWidget *object, gpointer userData) {
int result;
TargetT **backup;
(void)object;
backup = targetArrayCopy(self->targets);
grid = gtk_grid_new();
@ -1108,6 +1236,9 @@ void winProjectCreate(void) {
//***DEBUG***
self->windowData.filename = strdup("/home/scott/joeyapps/warehouse/Warehouse.joe");
loadProject(self);
for (int i=0; i<arrlen(self->recipes); i++) {
debug("Reading Recipe %d [%s] = [%s]\n", i, self->recipes[i]->key, self->recipes[i]->value);
}
}
@ -1117,6 +1248,7 @@ static void winProjectDelete(gpointer userData) {
utilWindowUnRegister(userData);
targetArrayDelete(&self->targets);
clearRecipeData(self);
DEL(self->buildHost);
DEL(self->buildUser);

View file

@ -41,7 +41,7 @@ pushd "${ROOT}" || exit &> /dev/null
if [[ ! -f ${INSTALLED}/cwalk-master/src/cwalk.c ]]; then
echo Unpacking Dependency: cwalk...
unzip ${THIRDPARTY}/cwalk-master.zip
unzip -u ${THIRDPARTY}/cwalk-master.zip
cp -f ${INSTALLED}/cwalk-master/include/cwalk.h ${INSTALLED}/include/.
fi

View file

@ -56,7 +56,7 @@
<property name="valign">center</property>
<property name="orientation">vertical</property>
<child>
<!-- n-columns=3 n-rows=3 -->
<!-- n-columns=4 n-rows=3 -->
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can-focus">False</property>
@ -124,7 +124,7 @@
<packing>
<property name="left-attach">1</property>
<property name="top-attach">0</property>
<property name="width">2</property>
<property name="width">3</property>
</packing>
</child>
<child>
@ -149,7 +149,21 @@
<packing>
<property name="left-attach">1</property>
<property name="top-attach">2</property>
<property name="width">2</property>
<property name="width">3</property>
</packing>
</child>
<child>
<object class="GtkButton" id="btnEdit">
<property name="label" translatable="yes">Edit</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="margin-start">15</property>
<signal name="clicked" handler="btnEditRecipeClicked" swapped="no"/>
</object>
<packing>
<property name="left-attach">3</property>
<property name="top-attach">1</property>
</packing>
</child>
</object>