Recipe dialog working, data being saved and loaded from projects.
This commit is contained in:
parent
73ee8388de
commit
f513dc3893
4 changed files with 178 additions and 26 deletions
|
@ -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)
|
||||
|
||||
|
||||
|
|
176
src/project.c
176
src/project.c
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Add table
Reference in a new issue