diff --git a/include/config.h.in b/include/config.h.in index 42cc681..630cd3d 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -29,8 +29,9 @@ #define JOEYDEV_VERSION "@joeydev_VERSION_MAJOR@.@joeydev_VERSION_MINOR@" -#define PROJECT_VERSION "1.0" // Used for file format versioning. -#define VICTOR_VERSION "1.0" // Used for file format versioning. +#define BUILD_SETTINGS_VERSION "1.0" // Used for file format versioning. +#define PROJECT_VERSION "1.0" // Used for file format versioning. +#define VICTOR_VERSION "1.0" // Used for file format versioning. #cmakedefine DEBUG_MODE diff --git a/include/utils.h b/include/utils.h index 284ff34..c7f8ab2 100644 --- a/include/utils.h +++ b/include/utils.h @@ -27,6 +27,16 @@ #include "common.h" +#ifdef _WIN32 +#define UTIL_PATH_CHAR '\\' +#else +#define UTIL_PATH_CHAR '/' +#endif + + +#define UTIL_PATH_MAX 1024 + + char *utilCreateString(char *format, ...); char *utilCreateStringVArgs(char *format, va_list args); void utilEnsureBufferSize(unsigned char **buffer, int *length, int wanted); @@ -35,6 +45,7 @@ gboolean utilFileOpen(WindowDataT *self, char *extension, char *what); gboolean utilFileSaveAs(WindowDataT *self, char *extension, char *what); WindowDataT *utilGetWindowData(GtkWidget *window); gboolean utilGetWidgetsFromMemory(char *resource, char *name[], GtkWidget **widgets[], gpointer userData); +gboolean utilMkDirP(const char *dir, const mode_t mode); gboolean utilQuestionDialog(GtkWidget *parent, char *title, char *question); void utilSetDirty(WindowDataT *self, gboolean dirty); void utilWindowRegister(gpointer windowData); diff --git a/src/project.c b/src/project.c index 974798d..4f901bc 100644 --- a/src/project.c +++ b/src/project.c @@ -53,9 +53,11 @@ typedef enum ProjectSectionTypeE ProjectSectionTypeT; typedef struct ProjectDataS { WindowDataT windowData; GtkWidget *treeProject; - GtkTreeStore *storeProject; - char *title; - char *filename; + char *configName; + char *buildHost; + int buildPort; + char *buildUser; + char *buildPassword; } ProjectDataT; typedef struct SectionDataS { @@ -78,7 +80,11 @@ static SectionDataT _sectionData[] = { }; +#define BUILD_SETTINGS_RESPONSE_TEST 1 + + static void addToTree(ProjectDataT *self, char *filename); +static void loadConfig(ProjectDataT *self); static void loadProject(ProjectDataT *self); EVENT void menuProjectFileNew(GtkWidget *object, gpointer userData); EVENT void menuProjectFileOpen(GtkWidget *object, gpointer userData); @@ -91,6 +97,7 @@ EVENT void menuProjectProjectProperties(GtkWidget *object, gpointer userDat EVENT void menuProjectBuildSettings(GtkWidget *object, gpointer userData); EVENT void menuProjectBuildBuild(GtkWidget *object, gpointer userData); EVENT void menuProjectHelpProject(GtkWidget *object, gpointer userData); +static void saveConfig(ProjectDataT *self); EVENT gboolean winProjectClose(GtkWidget *object, gpointer userData); static void winProjectDelete(gpointer userData); @@ -100,8 +107,9 @@ static void addToTree(ProjectDataT *self, char *filename) { char temp[4]; GtkTreeIter iterParent; GtkTreeIter iter; + GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(self->treeProject)); int fileLen; - int extLen; + int extLen; // Is it long enough? if (strlen(filename) > 2) { @@ -113,9 +121,9 @@ static void addToTree(ProjectDataT *self, char *filename) { extLen = strlen(_sectionData[section].extension) - 1; if (filename[fileLen - 1] == _sectionData[section].extension[extLen - 1] && filename[fileLen] == _sectionData[section].extension[extLen]) { snprintf(temp, 4, "%d", section); - gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(self->storeProject), &iterParent, temp); - gtk_tree_store_append(self->storeProject, &iter, &iterParent); - gtk_tree_store_set(self->storeProject, &iter, COL_FILENAME, filename, -1); + gtk_tree_model_get_iter_from_string(model, &iterParent, temp); + gtk_tree_store_append(GTK_TREE_STORE(model), &iter, &iterParent); + gtk_tree_store_set(GTK_TREE_STORE(model), &iter, COL_FILENAME, filename, -1); //***TODO*** Need to store extra RAW data somewhere. break; } @@ -125,6 +133,68 @@ static void addToTree(ProjectDataT *self, char *filename) { } +static void loadConfig(ProjectDataT *self) { + FILE *in = NULL; + char *line = NULL; + size_t len = 0; + size_t count = 0; + + self->configName = utilCreateString("%s%cjoeydev%cbuild.conf", g_get_user_config_dir(), UTIL_PATH_CHAR, UTIL_PATH_CHAR); + if (utilFileExists(self->configName)) { + in = fopen(self->configName, "rt"); + if (in != NULL) { + while (getline(&line, &len, in) != -1) { + if (strlen(line) > 0) line[strlen(line) - 1] = 0; + switch (count) { + case 0: // Version Number + case 1: // Separator line + break; + + case 2: // Host + DEL(self->buildHost); + self->buildHost = strdup(line); + break; + + case 3: // Port + self->buildPort = atoi(line); + break; + + case 4: // User + DEL(self->buildUser); + self->buildUser = strdup(line); + break; + + case 5: // Password + DEL(self->buildPassword); + self->buildPassword = strdup(line); + break; + + default: // Oops + break; + } + count++; + } + fclose(in); + DEL(line); + } else { + //***TODO*** Something bad happened. + } + } else { + // No config file. Set defaults. + DEL(self->buildHost); + DEL(self->buildUser); + DEL(self->buildPassword); + + self->buildHost = strdup("build.joeylib.com"); + self->buildPort = 816; + self->buildUser = strdup(g_get_user_name()); + self->buildPassword = strdup("SuperSecret"); + + saveConfig(self); + } +} + + static void loadProject(ProjectDataT *self) { FILE *in = NULL; char *line = NULL; @@ -157,30 +227,45 @@ static void loadProject(ProjectDataT *self) { EVENT void menuProjectFileNew(GtkWidget *object, gpointer userData) { + ProjectDataT *self = (ProjectDataT *)userData; + GtkTreeIter iter; + ProjectSectionTypeT i; + GtkTreeStore *store; + (void)object; + + gtk_tree_view_set_model(GTK_TREE_VIEW(self->treeProject), NULL); + + store = gtk_tree_store_new(1, G_TYPE_STRING); + + for (i=0; itreeProject), GTK_TREE_MODEL(store)); + g_object_unref(store); } EVENT void menuProjectFileOpen(GtkWidget *object, gpointer userData) { ProjectDataT *self = (ProjectDataT *)userData; - (void)object; - if (utilFileOpen((WindowDataT *)userData, "*.joe", "Project")) { + menuProjectFileNew(object, userData); loadProject(self); } } EVENT void menuProjectFileSave(GtkWidget *object, gpointer userData) { - ProjectDataT *self = (ProjectDataT *)userData; - FILE *out = NULL; + ProjectDataT *self = (ProjectDataT *)userData; + GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(self->treeProject)); + FILE *out = NULL; GtkTreeIter iter; GtkTreeIter child; char *temp; - (void)object; - // Do we need to save? if (self->windowData.isDirty == TRUE) { @@ -195,17 +280,17 @@ EVENT void menuProjectFileSave(GtkWidget *object, gpointer userData) { // Save! fprintf(out, "%s\n", PROJECT_VERSION); fprintf(out, "------------------------------------------------------------------------------\n"); - gtk_tree_model_get_iter_first(GTK_TREE_MODEL(self->storeProject), &iter); + gtk_tree_model_get_iter_first(model, &iter); do { - if (gtk_tree_model_iter_children(GTK_TREE_MODEL(self->storeProject), &child, &iter)) { + if (gtk_tree_model_iter_children(model, &child, &iter)) { do { //***TODO*** For RAW we need to store function name somewhere. - gtk_tree_model_get(GTK_TREE_MODEL(self->storeProject), &child, COL_FILENAME, &temp, -1); + gtk_tree_model_get(model, &child, COL_FILENAME, &temp, -1); fprintf(out, "%s\n", temp); DEL(temp); - } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(self->storeProject), &child)); + } while (gtk_tree_model_iter_next(model, &child)); } - } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(self->storeProject), &iter)); + } while (gtk_tree_model_iter_next(model, &iter)); fclose(out); // We're clean now. utilSetDirty((WindowDataT *)self, FALSE); @@ -282,13 +367,13 @@ EVENT void menuProjectProjectRemove(GtkWidget *object, gpointer userData) { // Is anything selected? if (gtk_tree_selection_get_selected(selection, &model, &iter)) { // Are we on a child item? - if (gtk_tree_store_iter_depth(self->storeProject, &iter) > 0) { + if (gtk_tree_store_iter_depth(GTK_TREE_STORE(model), &iter) > 0) { found = TRUE; } } if (found) { - gtk_tree_store_remove(self->storeProject, &iter); + gtk_tree_store_remove(GTK_TREE_STORE(model), &iter); utilSetDirty((WindowDataT *)self, TRUE); } else { // Provide help. @@ -309,7 +394,61 @@ EVENT void menuProjectProjectProperties(GtkWidget *object, gpointer userData) { EVENT void menuProjectBuildSettings(GtkWidget *object, gpointer userData) { + ProjectDataT *self = (ProjectDataT *)userData; + GtkWidget *dialogServerSettings; + GtkWidget *txtHost; + GtkWidget *txtPort; + GtkWidget *txtUser; + GtkWidget *txtPassword; + char *widgetNames[] = { + "dialogServerSettings", + "txtHost", + "txtPort", + "txtUser", + "txtPassword", + NULL + }; + GtkWidget **widgets[] = { + &dialogServerSettings, + &txtHost, + &txtPort, + &txtUser, + &txtPassword + }; + int result = 0; + char temp[6]; + (void)object; + + utilGetWidgetsFromMemory("/com/kangaroopunch/joeydev/BuildServer.glade", widgetNames, widgets, self); + + while (1) { + snprintf(temp, 6, "%d", self->buildPort); + gtk_entry_set_text(GTK_ENTRY(txtHost), self->buildHost); + gtk_entry_set_text(GTK_ENTRY(txtPort), temp); + gtk_entry_set_text(GTK_ENTRY(txtUser), self->buildUser); + gtk_entry_set_text(GTK_ENTRY(txtPassword), self->buildPassword); + result = gtk_dialog_run(GTK_DIALOG(dialogServerSettings)); + if (result == BUILD_SETTINGS_RESPONSE_TEST || result == GTK_RESPONSE_OK) { + // Save settings to disk. + DEL(self->buildHost); + DEL(self->buildUser); + DEL(self->buildPassword); + self->buildHost = strdup(gtk_entry_get_text(GTK_ENTRY(txtHost))); + self->buildPort = atoi(gtk_entry_get_text(GTK_ENTRY(txtPort))); + self->buildUser = strdup(gtk_entry_get_text(GTK_ENTRY(txtUser))); + self->buildPassword = strdup(gtk_entry_get_text(GTK_ENTRY(txtPassword))); + saveConfig(self); + + if (result == BUILD_SETTINGS_RESPONSE_TEST) { + // Run server connection test. + } + + break; + } + } + + gtk_widget_destroy(dialogServerSettings); } @@ -326,6 +465,31 @@ EVENT void menuProjectHelpProject(GtkWidget *object, gpointer userData) { } +static void saveConfig(ProjectDataT *self) { + char *temp; + FILE *out; + + // Make sure we have a config folder. + temp = utilCreateString("%s%cjoeydev", g_get_user_config_dir(), UTIL_PATH_CHAR); + utilMkDirP(temp, 0777); + DEL(temp); + + // Save config. + out = fopen(self->configName, "wt"); + if (out != NULL) { + fprintf(out, "%s\n", BUILD_SETTINGS_VERSION); + fprintf(out, "------------------------------------------------------------------------------\n"); + fprintf(out, "%s\n", self->buildHost); + fprintf(out, "%d\n", self->buildPort); + fprintf(out, "%s\n", self->buildUser); + fprintf(out, "%s\n", self->buildPassword); //***TODO*** This is hardly secure. + fclose(out); + } else { + //***TODO*** Something bad happened. + } +} + + EVENT gboolean winProjectClose(GtkWidget *object, gpointer userData) { // userData is not reliable due to menuVectorFileClose and util indirectly calling us. ProjectDataT *self = (ProjectDataT *)utilGetWindowData(object); @@ -358,8 +522,6 @@ void winProjectCreate(void) { }; GtkTreeViewColumn *col; GtkCellRenderer *renderer; - GtkTreeIter iter; - ProjectSectionTypeT i; // Set up instance data. self = NEW(ProjectDataT); @@ -376,15 +538,12 @@ void winProjectCreate(void) { renderer = gtk_cell_renderer_text_new(); gtk_tree_view_column_pack_start(col, renderer, TRUE); gtk_tree_view_column_add_attribute(col, renderer, "text", COL_FILENAME); - self->storeProject = gtk_tree_store_new(1, G_TYPE_STRING); - for (i=0; istoreProject, &iter, NULL); - gtk_tree_store_set(self->storeProject, &iter, COL_FILENAME, _sectionData[i].name, -1); - } + // Reset tree. + menuProjectFileNew(self->windowData.window, self); - gtk_tree_view_set_model(GTK_TREE_VIEW(self->treeProject), GTK_TREE_MODEL(self->storeProject)); - g_object_unref(self->storeProject); + // Load server settings. + loadConfig(self); // Register window & show it. utilWindowRegister(self); @@ -401,6 +560,11 @@ static void winProjectDelete(gpointer userData) { utilWindowUnRegister(userData); + DEL(self->buildHost); + DEL(self->buildUser); + DEL(self->buildPassword); + DEL(self->configName); + DEL(self); } diff --git a/src/utils.c b/src/utils.c index 54bb83a..e9995fe 100644 --- a/src/utils.c +++ b/src/utils.c @@ -20,9 +20,17 @@ */ +#include #include "utils.h" +#ifdef _WIN32 +#define ourMkdir(p,m) mkdir(p) +#else +#define ourMkdir mkdir +#endif + + typedef struct WindowListS { GtkWidget *key; WindowDataT *value; @@ -199,6 +207,67 @@ gboolean utilGetWidgetsFromMemory(char *resource, char *name[], GtkWidget **widg } +gboolean utilMkDirP(const char *dir, const mode_t mode) { + char tmp[UTIL_PATH_MAX]; + char *p = NULL; + struct stat sb; + size_t len; + + // Make copy of dir. + len = strnlen(dir, UTIL_PATH_MAX); + if (len == 0 || len == UTIL_PATH_MAX) { + return -1; + } + memcpy(tmp, dir, len); + tmp[len] = '\0'; + + // Remove trailing slash. + if (tmp[len - 1] == UTIL_PATH_CHAR) { + tmp[len - 1] = '\0'; + } + + // Does it already exist? + if (stat(tmp, &sb) == 0) { + if (S_ISDIR(sb.st_mode)) { + return TRUE; + } + } + + // Recursive mkdir. + for (p = tmp + 1; *p; p++) { + if (*p == UTIL_PATH_CHAR) { + *p = 0; + if (stat(tmp, &sb) != 0) { + // Does not exist - create it. + if (ourMkdir(tmp, mode) < 0) { + return FALSE; + } + } else { + if (!S_ISDIR(sb.st_mode)) { + // Not a directory + return FALSE; + } + } + *p = UTIL_PATH_CHAR; + } + } + // Check path + if (stat(tmp, &sb) != 0) { + // Does not exist - create it. + if (ourMkdir(tmp, mode) < 0) { + return FALSE; + } + } else { + if (!S_ISDIR(sb.st_mode)) { + // Not a directory + return FALSE; + } + } + + return TRUE; +} + + gboolean utilQuestionDialog(GtkWidget *parent, char *title, char *question) { GtkWidget *dialog; int response; diff --git a/ui/BuildServer.glade b/ui/BuildServer.glade new file mode 100644 index 0000000..ad51254 --- /dev/null +++ b/ui/BuildServer.glade @@ -0,0 +1,174 @@ + + + + + + False + Build Server Settings + 200 + applications-system + dialog + + + False + vertical + 2 + + + False + end + + + Test + True + True + True + + + True + True + 0 + + + + + OK + True + True + True + + + True + True + 1 + + + + + False + False + 0 + + + + + + True + False + 5 + 5 + + + True + False + end + Host: + right + + + 0 + 0 + + + + + True + False + end + Port: + right + + + 0 + 1 + + + + + True + False + end + User: + right + + + 0 + 2 + + + + + True + False + end + Password: + right + + + 0 + 3 + + + + + True + True + True + url + + + 1 + 0 + + + + + True + True + True + digits + + + 1 + 1 + + + + + True + True + True + name + + + 1 + 2 + + + + + True + True + True + password + + + 1 + 3 + + + + + False + True + 1 + + + + + + btnTest + btnOkay + + + diff --git a/ui/Project.glade b/ui/Project.glade index 50f2c1f..574d9c9 100644 --- a/ui/Project.glade +++ b/ui/Project.glade @@ -144,7 +144,7 @@ True False - Settings... + Server Settings... True diff --git a/ui/joeydev.gresource.xml b/ui/joeydev.gresource.xml index 9141970..e740fbf 100644 --- a/ui/joeydev.gresource.xml +++ b/ui/joeydev.gresource.xml @@ -3,6 +3,7 @@ JoeyDev.glade Project.glade + BuildServer.glade Vector.glade Logo.png