Start of Targets dialog.

This commit is contained in:
Scott Duensing 2023-01-24 20:08:34 -06:00
parent 6ac1f11291
commit 2469ec2ca2
6 changed files with 261 additions and 51 deletions

View file

@ -48,9 +48,11 @@ typedef struct HTTPS {
} HTTPT;
HTTPT *httpDownload(HTTPCallback callback, char *filename, char *url);
void httpShutdown(void);
void httpStartup(void);
HTTPT *httpDownload(HTTPCallback callback, char *filename, char *url);
void httpShutdown(void);
void httpStartup(void);
gboolean httpWaitForDownload(void);
void httpWaitForDownloadCallback(HTTPT *download);
#endif // HTTP_H

View file

@ -40,10 +40,12 @@
char *utilCreateString(char *format, ...);
char *utilCreateStringVArgs(char *format, va_list args);
char *utilDeobfuscateASCII(char *obfuscated);
void utilDequote(char *string);
void utilEnsureBufferSize(unsigned char **buffer, int *length, int wanted);
gboolean utilFileExists(char *filename);
gboolean utilFileOpen(WindowDataT *self, char *extension, char *what);
gboolean utilFileSaveAs(WindowDataT *self, char *extension, char *what);
char *utilGetToken(char *input, char *delimit, char *openblock, char *closeblock);
WindowDataT *utilGetWindowData(GtkWidget *window);
gboolean utilGetWidgetsFromMemory(char *resource, char *name[], GtkWidget **widgets[], gpointer userData);
gboolean utilMkDirP(const char *dir, const mode_t mode);

View file

@ -20,11 +20,17 @@
*/
#pragma clang diagnostic push
#pragma ide diagnostic ignored "EndlessLoop"
#include "http.h"
static CURLM *_curlMulti = NULL;
static HTTPT **_activeHTTPs = NULL;
static CURLM *_curlMulti = NULL;
static HTTPT **_activeHTTPs = NULL;
static gboolean _httpTestComplete = FALSE;
static gboolean _httpTestSuccess = FALSE;
gboolean httpUpdate(gpointer userData); // Not static
@ -150,6 +156,22 @@ gboolean httpUpdate(gpointer userData) {
}
gboolean httpWaitForDownload(void) {
_httpTestComplete = FALSE;
// This loop seriously breaks CLion's syntax highlighting for the rest of the function.
while (_httpTestComplete == FALSE) {
gtk_main_iteration();
}
return _httpTestSuccess;
}
void httpWaitForDownloadCallback(HTTPT *download) {
_httpTestComplete = TRUE;
_httpTestSuccess = download->success;
}
static size_t httpWrite(char *data, size_t num, size_t length, void *userp) {
HTTPT *download = (HTTPT *)userp;
@ -171,3 +193,6 @@ static size_t httpWrite(char *data, size_t num, size_t length, void *userp) {
return num * length;
}
#pragma clang diagnostic pop

View file

@ -22,7 +22,6 @@
#pragma clang diagnostic push
#pragma ide diagnostic ignored "cppcoreguidelines-narrowing-conversions"
#pragma ide diagnostic ignored "EndlessLoop"
#include "common.h"
@ -53,6 +52,17 @@ enum ProjectSectionTypeE {
typedef enum ProjectSectionTypeE ProjectSectionTypeT;
typedef struct ArchS {
char *name;
gboolean selected;
} ArchT;
typedef struct TargetS {
char *name;
char *longName;
ArchT **archs;
} TargetT;
typedef struct ProjectDataS {
WindowDataT windowData;
GtkWidget *treeProject;
@ -62,6 +72,7 @@ typedef struct ProjectDataS {
int buildSSHPort;
char *buildUser;
char *buildPassword;
TargetT **targets;
} ProjectDataT;
typedef struct SectionDataS {
@ -84,15 +95,10 @@ static SectionDataT _sectionData[] = {
};
static gboolean _httpTestComplete = FALSE;
static gboolean _httpTestSuccess = FALSE;
#define BUILD_SETTINGS_RESPONSE_TEST 1
static void addToTree(ProjectDataT *self, char *filename);
static void httpTest(HTTPT *download);
static void loadConfig(ProjectDataT *self);
static void loadProject(ProjectDataT *self);
EVENT void menuProjectFileNew(GtkWidget *object, gpointer userData);
@ -102,11 +108,12 @@ EVENT void menuProjectFileSaveAs(GtkWidget *object, gpointer userData);
EVENT void menuProjectFileClose(GtkWidget *object, gpointer userData);
EVENT void menuProjectProjectAdd(GtkWidget *object, gpointer userData);
EVENT void menuProjectProjectRemove(GtkWidget *object, gpointer userData);
EVENT void menuProjectProjectProperties(GtkWidget *object, gpointer userData);
EVENT void menuProjectBuildSettings(GtkWidget *object, gpointer userData);
EVENT void menuProjectBuildTargets(GtkWidget *object, gpointer userData);
EVENT void menuProjectBuildBuild(GtkWidget *object, gpointer userData);
EVENT void menuProjectHelpProject(GtkWidget *object, gpointer userData);
static void saveConfig(ProjectDataT *self);
static gboolean updateBuildOptions(ProjectDataT *self);
EVENT gboolean winProjectClose(GtkWidget *object, gpointer userData);
static void winProjectDelete(gpointer userData);
@ -142,12 +149,6 @@ static void addToTree(ProjectDataT *self, char *filename) {
}
static void httpTest(HTTPT *download) {
_httpTestComplete = TRUE;
_httpTestSuccess = download->success;
}
static void loadConfig(ProjectDataT *self) {
FILE *in = NULL;
char *line = NULL;
@ -408,11 +409,6 @@ EVENT void menuProjectProjectRemove(GtkWidget *object, gpointer userData) {
}
EVENT void menuProjectProjectProperties(GtkWidget *object, gpointer userData) {
}
EVENT void menuProjectBuildSettings(GtkWidget *object, gpointer userData) {
ProjectDataT *self = (ProjectDataT *)userData;
GtkWidget *dialog;
@ -446,8 +442,6 @@ EVENT void menuProjectBuildSettings(GtkWidget *object, gpointer userData) {
&btnOkay
};
char temp[6];
char *name = NULL;
char *url = NULL;
int result = 0;
SSHT *ssh = NULL;
char *error = NULL;
@ -481,19 +475,9 @@ EVENT void menuProjectBuildSettings(GtkWidget *object, gpointer userData) {
gtk_widget_set_sensitive(btnTest, FALSE);
gtk_widget_set_sensitive(btnOkay, FALSE);
// Run server connection tests - HTTP.
name = utilCreateString("%s%cjoeydev%cjoeydev.info", g_get_user_config_dir(), UTIL_PATH_CHAR, UTIL_PATH_CHAR);
url = utilCreateString("http://%s:%d/joeydev.info", self->buildHost, self->buildHTTPPort);
_httpTestComplete = FALSE;
httpDownload(httpTest, name, url);
// This loop seriously breaks CLion's syntax highlighting.
while (_httpTestComplete == FALSE) {
gtk_main_iteration();
}
if (_httpTestSuccess == FALSE) {
if (updateBuildOptions(self) == FALSE) {
error = utilCreateString("Unable to connect to HTTP port.");
}
DEL(url);
DEL(name);
// Run server connection tests - SSH.
ssh = sshConnect(self->buildHost, self->buildSSHPort, self->buildUser, self->buildPassword);
if (ssh) {
@ -522,6 +506,8 @@ EVENT void menuProjectBuildSettings(GtkWidget *object, gpointer userData) {
gtk_widget_set_sensitive(btnTest, TRUE);
gtk_widget_set_sensitive(btnOkay, TRUE);
} else {
// Try to load the build options in case they didn't click TEST.
updateBuildOptions(self);
// Close dialog on OKAY but not TEST.
break;
}
@ -533,6 +519,62 @@ EVENT void menuProjectBuildSettings(GtkWidget *object, gpointer userData) {
}
EVENT void menuProjectBuildTargets(GtkWidget *object, gpointer userData) {
ProjectDataT *self = (ProjectDataT *)userData;
GtkWidget *dialog;
GtkWidget *contentArea;
GtkWidget *grid;
GtkWidget *widget;
TargetT *t;
ArchT *a;
char *temp;
int i;
int j;
int result;
grid = gtk_grid_new();
gtk_grid_set_column_homogeneous(GTK_GRID(grid), FALSE);
gtk_grid_set_row_homogeneous(GTK_GRID(grid), TRUE);
gtk_grid_set_column_spacing(GTK_GRID(grid), 15);
gtk_grid_set_row_spacing(GTK_GRID(grid), 5);
for (i=0; i<arrlen(self->targets); i++) {
t = self->targets[i];
temp = utilCreateString("%s:", t->longName);
widget = gtk_label_new(temp);
DEL(temp);
gtk_label_set_line_wrap(GTK_LABEL(widget), FALSE);
gtk_label_set_xalign(GTK_LABEL(widget), 1.0);
gtk_grid_attach(GTK_GRID(grid), widget, 0, i, 1, 1);
for (j=0; j<arrlen(t->archs); j++) {
a = t->archs[j];
widget = gtk_check_button_new_with_label(a->name);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), a->selected);
gtk_grid_attach(GTK_GRID(grid), widget, j + 1, i, 1, 1);
}
}
dialog = gtk_dialog_new_with_buttons(
"Targets",
GTK_WINDOW(self->windowData.window),
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
"_Cancel",
GTK_RESPONSE_CANCEL,
"_OK",
GTK_RESPONSE_OK,
NULL
);
contentArea = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
gtk_container_add(GTK_CONTAINER(contentArea), grid);
gtk_widget_show_all(dialog);
result = gtk_dialog_run(dialog);
gtk_widget_destroy(dialog);
}
EVENT void menuProjectBuildBuild(GtkWidget *object, gpointer userData) {
}
@ -574,6 +616,90 @@ static void saveConfig(ProjectDataT *self) {
}
static gboolean updateBuildOptions(ProjectDataT *self) {
char *test = NULL;
char *name = NULL;
char *url = NULL;
gboolean result = FALSE;
FILE *in = NULL;
char *line = NULL;
size_t len = 0;
char *c = NULL;
TargetT *t = NULL;
ArchT *a = NULL;
// This updates the build options file without clobbering one if it already exists and we fail to get a new one.
test = utilCreateString("%s%cjoeydev%cjoeydev.temp", g_get_user_config_dir(), UTIL_PATH_CHAR, UTIL_PATH_CHAR);
name = utilCreateString("%s%cjoeydev%cjoeydev.info", g_get_user_config_dir(), UTIL_PATH_CHAR, UTIL_PATH_CHAR);
url = utilCreateString("http://%s:%d/joeydev.info", self->buildHost, self->buildHTTPPort);
httpDownload(httpWaitForDownloadCallback, test, url);
if (httpWaitForDownload() == TRUE) {
unlink(name);
rename(test, name);
result = TRUE;
}
// Unload current target listing.
while (arrlen(self->targets) > 0) {
t = self->targets[0];
while (arrlen(t->archs) > 0) {
a = t->archs[0];
DEL(a->name);
arrdel(t->archs, 0);
}
DEL(t->name);
DEL(t->longName);
arrdel(self->targets, 0);
}
// If there's a list of targets on the disk, load them.
if (utilFileExists(name) == TRUE) {
in = fopen(name, "rt");
if (in != NULL) {
while (getline(&line, &len, in) != -1) {
if (strlen(line) > 0) line[strlen(line) - 1] = 0;
// Is this a 'target' line?
c = utilGetToken(line, " ", "\"", "\"");
utilDequote(c);
if (strcasecmp(c, "target") == 0) {
t = NEW(TargetT);
// Short name.
c = utilGetToken(NULL, " ", "\"", "\"");
utilDequote(c);
t->name = strdup(c);
// Long name.
c = utilGetToken(NULL, " ", "\"", "\"");
utilDequote(c);
t->longName = strdup(c);
// Architectures.
do {
c = utilGetToken(NULL, " ", "\"", "\"");
if (c != NULL) {
utilDequote(c);
a = NEW(ArchT);
a->name = strdup(c);
a->selected = TRUE;
arrput(t->archs, a);
}
} while (c != NULL);
arrput(self->targets, t);
}
}
fclose(in);
DEL(line);
}
}
DEL(url);
DEL(name);
DEL(test);
return result;
}
EVENT gboolean winProjectClose(GtkWidget *object, gpointer userData) {
// userData is not reliable due to menuVectorFileClose and util indirectly calling us.
ProjectDataT *self = (ProjectDataT *)utilGetWindowData(object);
@ -633,6 +759,9 @@ void winProjectCreate(void) {
utilWindowRegister(self);
gtk_widget_show_all(self->windowData.window);
// Attempt to load build settings from build server.
updateBuildOptions(self);
//***DEBUG***
self->windowData.filename = strdup("/home/scott/code/joeydev/cmake-build-debug/test.joe");
loadProject(self);

View file

@ -97,6 +97,18 @@ char *utilDeobfuscateASCII(char *obfuscated) {
}
void utilDequote(char *string) {
int x;
if (string[0] == '"' || string[strlen(string) - 1] == '"') {
string[strlen(string) - 1] = 0;
for (x=1; x<strlen(string) + 1; x++) {
string[x - 1] = string[x];
}
}
}
void utilEnsureBufferSize(unsigned char **buffer, int *length, int wanted) {
unsigned char *temp = NULL;
@ -206,6 +218,52 @@ gboolean utilFileSaveAs(WindowDataT *self, char *extension, char *what) {
}
// https://stackoverflow.com/questions/26187037/in-c-split-char-on-spaces-with-strtok-function-except-if-between-quotes
char *utilGetToken(char *input, char *delimit, char *openblock, char *closeblock) {
static char *token = NULL;
char *lead = NULL;
char *block = NULL;
int iBlock = 0;
int iBlockIndex = 0;
if (input != NULL) {
token = input;
lead = input;
} else {
lead = token;
if (*token == 0) lead = NULL;
}
while (*token != 0) {
if (iBlock) {
if (closeblock[iBlockIndex] == *token) {
iBlock = 0;
}
token++;
continue;
}
if ((block = strchr(openblock, *token)) != NULL) {
iBlock = 1;
iBlockIndex = block - openblock;
token++;
continue;
}
if (strchr(delimit, *token) != NULL) {
*token = 0;
token++;
break;
}
token++;
}
return lead;
}
WindowDataT *utilGetWindowData(GtkWidget *window) {
return hmget(_windowList, window);
}

View file

@ -111,21 +111,6 @@
<signal name="activate" handler="menuProjectProjectRemove" swapped="no"/>
</object>
</child>
<child>
<object class="GtkSeparatorMenuItem">
<property name="visible">True</property>
<property name="can-focus">False</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="menuProjectProjectProperties">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Properties...</property>
<property name="use-underline">True</property>
<signal name="activate" handler="menuProjectProjectProperties" swapped="no"/>
</object>
</child>
</object>
</child>
</object>
@ -149,6 +134,15 @@
<signal name="activate" handler="menuProjectBuildSettings" swapped="no"/>
</object>
</child>
<child>
<object class="GtkMenuItem" id="menuProjectBuildTargets">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Targets...</property>
<property name="use-underline">True</property>
<signal name="activate" handler="menuProjectBuildTargets" swapped="no"/>
</object>
</child>
<child>
<object class="GtkSeparatorMenuItem">
<property name="visible">True</property>