SF.net SVN: geany: [1200] trunk
eht16 at users.sourceforge.net
eht16 at xxxxx
Wed Jan 17 23:44:08 UTC 2007
Revision: 1200
http://svn.sourceforge.net/geany/?rev=1200&view=rev
Author: eht16
Date: 2007-01-17 15:44:08 -0800 (Wed, 17 Jan 2007)
Log Message:
-----------
Added properties dialog (still far away from state ready).
Added file_patterns field.
Added utils_mkdir().
Modified Paths:
--------------
trunk/ChangeLog
trunk/src/project.c
trunk/src/project.h
trunk/src/utils.c
trunk/src/utils.h
Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog 2007-01-17 17:42:23 UTC (rev 1199)
+++ trunk/ChangeLog 2007-01-17 23:44:08 UTC (rev 1200)
@@ -1,3 +1,11 @@
+2007-01-17 Enrico Tröger <enrico.troeger at uvena.de>
+
+ * src/project.c, src/project.h:
+ Added properties dialog (still far away from state ready).
+ Added file_patterns field.
+ * src/utils.c, src/utils.h: Added utils_mkdir().
+
+
2007-01-17 Nick Treleaven <nick.treleaven at btinternet.com>
* src/callbacks.c, doc/geany.docbook:
Modified: trunk/src/project.c
===================================================================
--- trunk/src/project.c 2007-01-17 17:42:23 UTC (rev 1199)
+++ trunk/src/project.c 2007-01-17 23:44:08 UTC (rev 1200)
@@ -22,19 +22,44 @@
*/
#include "geany.h"
+
+#include <string.h>
+
#include "project.h"
#include "dialogs.h"
#include "support.h"
+#include "utils.h"
+#include "ui_utils.h"
+#ifdef G_OS_WIN32
+# include "win32.h"
+#endif
+
+// simple struct to keep references to the elements of the properties dialog
+typedef struct
+{
+ GtkWidget *dialog;
+ GtkWidget *name;
+ GtkWidget *description;
+ GtkWidget *file_name;
+ GtkWidget *base_path;
+ GtkWidget *patterns;
+} PropertyDialogElements;
+
+
+
+static void on_properties_dialog_response(GtkDialog *dialog, gint response,
+ PropertyDialogElements *e);
+static void on_file_open_button_clicked(GtkButton *button, GtkWidget *entry);
+static void on_folder_open_button_clicked(GtkButton *button, GtkWidget *entry);
static gboolean close_open_project();
+static void on_name_entry_changed(GtkEditable *editable, PropertyDialogElements *e);
void project_new()
{
if (! close_open_project()) return;
- // simply create an empty project and show the properties dialog
- app->project = g_new0(GeanyProject, 1);
project_properties();
}
@@ -66,11 +91,167 @@
void project_properties()
{
- g_return_if_fail(app->project != NULL);
+ gchar *ok_button;
+ GtkWidget *vbox;
+ GtkWidget *table;
+ GtkWidget *image;
+ GtkWidget *button;
+ GtkWidget *bbox;
+ GtkWidget *label;
+ GtkWidget *swin;
+ PropertyDialogElements *e = g_new(PropertyDialogElements, 1);
+
+ if (app->project == NULL)
+ ok_button = GTK_STOCK_NEW;
+ else
+ ok_button = GTK_STOCK_OK;
+
+ e->dialog = gtk_dialog_new_with_buttons(_("Project properties"), GTK_WINDOW(app->window),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ ok_button, GTK_RESPONSE_OK, NULL);
+ vbox = ui_dialog_vbox_new(GTK_DIALOG(e->dialog));
+
+
+ table = gtk_table_new(5, 2, FALSE);
+ gtk_table_set_row_spacings(GTK_TABLE(table), 5);
+ gtk_table_set_col_spacings(GTK_TABLE(table), 10);
+
+ label = gtk_label_new(_("Name:"));
+ gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment(GTK_MISC(label), 1, 0);
+
+ e->name = gtk_entry_new();
+ gtk_table_attach(GTK_TABLE(table), e->name, 1, 2, 0, 1,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+
+ label = gtk_label_new(_("Description:"));
+ gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (GTK_FILL), 0, 0);
+ gtk_misc_set_alignment(GTK_MISC(label), 1, 0);
+
+ e->description = gtk_text_view_new();
+ swin = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(swin),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(swin), GTK_WIDGET(e->description));
+ gtk_table_attach(GTK_TABLE(table), swin, 1, 2, 1, 2,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+
+ label = gtk_label_new(_("File location:"));
+ gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment(GTK_MISC(label), 1, 0);
+
+ e->file_name = gtk_entry_new();
+ button = gtk_button_new();
+ g_signal_connect((gpointer) button, "clicked",
+ G_CALLBACK(on_file_open_button_clicked), e->file_name);
+ image = gtk_image_new_from_stock("gtk-open", GTK_ICON_SIZE_BUTTON);
+ gtk_container_add(GTK_CONTAINER(button), image);
+ bbox = gtk_hbox_new(FALSE, 6);
+ gtk_box_pack_start_defaults(GTK_BOX(bbox), e->file_name);
+ gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0);
+ gtk_table_attach(GTK_TABLE(table), bbox, 1, 2, 2, 3,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+
+ label = gtk_label_new(_("Base path:"));
+ gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment(GTK_MISC(label), 1, 0);
+
+ e->base_path = gtk_entry_new();
+ button = gtk_button_new();
+ g_signal_connect((gpointer) button, "clicked",
+ G_CALLBACK(on_folder_open_button_clicked), e->base_path);
+ image = gtk_image_new_from_stock("gtk-open", GTK_ICON_SIZE_BUTTON);
+ gtk_container_add(GTK_CONTAINER(button), image);
+ bbox = gtk_hbox_new(FALSE, 6);
+ gtk_box_pack_start_defaults(GTK_BOX(bbox), e->base_path);
+ gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0);
+ gtk_table_attach(GTK_TABLE(table), bbox, 1, 2, 3, 4,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+
+ label = gtk_label_new(_("File patterns:"));
+ // <small>Separate multiple patterns by a new line</small>
+ gtk_table_attach(GTK_TABLE(table), label, 0, 1, 4, 5,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (GTK_FILL), 0, 0);
+ gtk_misc_set_alignment(GTK_MISC(label), 1, 0);
+
+ e->patterns = gtk_text_view_new();
+ swin = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(swin),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(swin), GTK_WIDGET(e->patterns));
+ gtk_table_attach(GTK_TABLE(table), swin, 1, 2, 4, 5,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+
+
+
+ gtk_container_add(GTK_CONTAINER(vbox), table);
+
+ // signals
+ if (app->project == NULL)
+ { // this should only be done when we are about to create a new project
+ g_signal_connect((gpointer) e->name, "changed", G_CALLBACK(on_name_entry_changed), e);
+ // run the callback manually to initialise the base_path and file_name fields
+ on_name_entry_changed(GTK_EDITABLE(e->name), e);
+ }
+ g_signal_connect((gpointer) e->dialog, "response",
+ G_CALLBACK(on_properties_dialog_response), e);
+
+ // if we have an already open project, fill the elements with the appropriate data
+ if (app->project != NULL)
+ {
+ GeanyProject *p = app->project;
+
+ gtk_entry_set_text(GTK_ENTRY(e->name), p->name);
+
+ if (p->description != NULL)
+ { // set text
+ GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(e->description));
+ gtk_text_buffer_set_text(buffer, p->description, -1);
+ }
+
+ if (p->file_patterns != NULL)
+ { // set the file patterns
+ gint i;
+ gint len = g_strv_length(p->file_patterns);
+ GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(e->patterns));
+ GString *str = g_string_sized_new(len * 4);
+
+ for (i = 0; i < len; i++)
+ {
+ if (p->file_patterns[i] != NULL)
+ {
+ g_string_append(str, p->file_patterns[i]);
+ g_string_append_c(str, '\n');
+ }
+ }
+ gtk_text_buffer_set_text(buffer, str->str, -1);
+ g_string_free(str, FALSE); // can this leak?
+ }
+
+ gtk_entry_set_text(GTK_ENTRY(e->file_name), p->file_name);
+ gtk_entry_set_text(GTK_ENTRY(e->base_path), p->base_path);
+ }
+
+ gtk_widget_show_all(e->dialog);
}
-/* checks whether there is an already open project and asks the user if he want to close it or
+/* checks whether there is an already open project and asks the user if he wants to close it or
* abort the current action. Returns FALSE when the current action(the caller) should be cancelled
* and TRUE if we can go ahead */
static gboolean close_open_project()
@@ -91,3 +272,233 @@
else
return TRUE;
}
+
+
+#define SHOW_ERR(...) dialogs_show_msgbox(GTK_MESSAGE_ERROR, __VA_ARGS__)
+#define MAX_LEN 50
+
+static void on_properties_dialog_response(GtkDialog *dialog, gint response,
+ PropertyDialogElements *e)
+{
+ if (response == GTK_RESPONSE_OK && e != NULL)
+ {
+ const gchar *name, *file_name, *base_path;
+ gint name_len;
+ GeanyProject *p;
+
+ name = gtk_entry_get_text(GTK_ENTRY(e->name));
+ name_len = strlen(name);
+ if (name_len == 0)
+ {
+ SHOW_ERR(_("The specified project name is too short."));
+ gtk_widget_grab_focus(e->name);
+ return;
+ }
+ else if (name_len > MAX_LEN)
+ {
+ SHOW_ERR(_("The specified project name is too long (max. %d characters)."), MAX_LEN);
+ gtk_widget_grab_focus(e->name);
+ return;
+ }
+
+ file_name = gtk_entry_get_text(GTK_ENTRY(e->file_name));
+ if (strlen(file_name) == 0)
+ {
+ SHOW_ERR(_("You have specified an invalid project file location."));
+ gtk_widget_grab_focus(e->file_name);
+ return;
+ }
+
+ base_path = gtk_entry_get_text(GTK_ENTRY(e->base_path));
+ if (strlen(base_path) == 0)
+ {
+ SHOW_ERR(_("You have specified an invalid project base path."));
+ gtk_widget_grab_focus(e->base_path);
+ return;
+ }
+ else
+ { // check whether the given directory actually exists
+ gchar *locale_path = utils_get_locale_from_utf8(base_path);
+ if (! g_file_test(locale_path, G_FILE_TEST_IS_DIR))
+ {
+ if (dialogs_show_question(
+ _("The specified project base path does not exist. Should it be created?")))
+ {
+ utils_mkdir(locale_path);
+ }
+ else
+ {
+ g_free(locale_path);
+ gtk_widget_grab_focus(e->base_path);
+ return;
+ }
+ }
+ g_free(locale_path);
+ }
+
+ // finally test whether the given project file can be written
+ if (utils_write_file(file_name, "") != 0)
+ {
+ SHOW_ERR(_("Project file could not be written."));
+ gtk_widget_grab_focus(e->file_name);
+ return;
+ }
+
+ app->project = g_new0(GeanyProject, 1);
+ p = app->project;
+
+ p->name = g_strdup(name);
+ { // get and set the project description
+ GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(e->description));
+ GtkTextIter start, end;
+ gtk_text_buffer_get_start_iter(buffer, &start);
+ gtk_text_buffer_get_end_iter(buffer, &end);
+ p->description = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
+ }
+ p->file_name = g_strdup(file_name);
+ p->base_path = g_strdup(base_path);
+
+ { // get and set the project file patterns
+ GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(e->patterns));
+ GtkTextIter start, end;
+ gchar *tmp;
+ gtk_text_buffer_get_start_iter(buffer, &start);
+ gtk_text_buffer_get_end_iter(buffer, &end);
+ tmp = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
+ g_strfreev(p->file_patterns);
+ p->file_patterns = g_strsplit(tmp, "\n", -1);
+ g_free(tmp);
+ }
+ }
+
+ gtk_widget_destroy(GTK_WIDGET(dialog));
+ g_free(e);
+}
+
+
+static void on_file_open_button_clicked(GtkButton *button, GtkWidget *entry)
+{
+#ifdef G_OS_WIN32
+ /// TODO write me
+ //win32_show_project_file_dialog(item);
+#else
+ GtkWidget *dialog;
+
+ // initialise the dialog
+ dialog = gtk_file_chooser_dialog_new(_("Choose project filename"), NULL,
+ GTK_FILE_CHOOSER_ACTION_SAVE,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
+ gtk_window_set_destroy_with_parent(GTK_WINDOW(dialog), TRUE);
+ gtk_window_set_skip_taskbar_hint(GTK_WINDOW(dialog), TRUE);
+ gtk_window_set_type_hint(GTK_WINDOW(dialog), GDK_WINDOW_TYPE_HINT_DIALOG);
+ gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
+
+ { // set filename
+ gchar *locale_filename = utils_get_locale_from_utf8(gtk_entry_get_text(GTK_ENTRY(entry)));
+
+ if (g_path_is_absolute(locale_filename))
+ gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), locale_filename);
+ else
+ gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), locale_filename);
+ g_free(locale_filename);
+ }
+
+ // run it
+ if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
+ {
+ gchar *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
+ gchar *utf8_filename = utils_get_utf8_from_locale(filename);
+
+ gtk_entry_set_text(GTK_ENTRY(entry), utf8_filename);
+
+ g_free(utf8_filename);
+ g_free(filename);
+ }
+
+ gtk_widget_destroy(dialog);
+#endif
+}
+
+
+static void on_folder_open_button_clicked(GtkButton *button, GtkWidget *entry)
+{
+#ifdef G_OS_WIN32
+ /// TODO write me
+ //win32_show_project_folder_dialog(item);
+#else
+ GtkWidget *dialog;
+
+ // initialise the dialog
+ dialog = gtk_file_chooser_dialog_new(_("Choose project base path"), NULL,
+ GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
+ gtk_window_set_destroy_with_parent(GTK_WINDOW(dialog), TRUE);
+ gtk_window_set_skip_taskbar_hint(GTK_WINDOW(dialog), TRUE);
+ gtk_window_set_type_hint(GTK_WINDOW(dialog), GDK_WINDOW_TYPE_HINT_DIALOG);
+ gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
+
+ { // set filename
+ gchar *locale_filename = utils_get_locale_from_utf8(gtk_entry_get_text(GTK_ENTRY(entry)));
+
+ if (g_path_is_absolute(locale_filename))
+ gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), locale_filename);
+ else
+ gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), locale_filename);
+ g_free(locale_filename);
+ }
+
+ // run it
+ if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
+ {
+ gchar *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
+ gchar *utf8_filename = utils_get_utf8_from_locale(filename);
+
+ gtk_entry_set_text(GTK_ENTRY(entry), utf8_filename);
+
+ g_free(utf8_filename);
+ g_free(filename);
+ }
+
+ gtk_widget_destroy(dialog);
+#endif
+}
+
+// "projects" is part of the default project base path so be carefully when translating
+// please avoid special characters and spaces, look at the source for details or ask Frank
+#define PROJECT_DIR _("projects")
+
+/* sets the project base path and the project file name according to the project name */
+/// TODO cancel the process once base_path resp. file_name has been changed manually
+static void on_name_entry_changed(GtkEditable *editable, PropertyDialogElements *e)
+{
+ gchar *base_path;
+ gchar *file_name;
+ gchar *name;
+
+ name = gtk_editable_get_chars(editable, 0, -1);
+ if (name != NULL && strlen(name) > 0)
+ {
+ base_path = g_strconcat(
+ GEANY_HOME_DIR, G_DIR_SEPARATOR_S, PROJECT_DIR, G_DIR_SEPARATOR_S,
+ name, G_DIR_SEPARATOR_S, NULL);
+ file_name = g_strconcat(
+ GEANY_HOME_DIR, G_DIR_SEPARATOR_S, PROJECT_DIR, G_DIR_SEPARATOR_S,
+ name, G_DIR_SEPARATOR_S, name, ".geany", NULL);
+ g_free(name);
+ }
+ else
+ {
+ base_path = g_strconcat(
+ GEANY_HOME_DIR, G_DIR_SEPARATOR_S, PROJECT_DIR, G_DIR_SEPARATOR_S, NULL);
+ file_name = g_strconcat(
+ GEANY_HOME_DIR, G_DIR_SEPARATOR_S,PROJECT_DIR, G_DIR_SEPARATOR_S, NULL);
+ }
+
+ gtk_entry_set_text(GTK_ENTRY(e->base_path), base_path);
+ gtk_entry_set_text(GTK_ENTRY(e->file_name), file_name);
+
+ g_free(base_path);
+ g_free(file_name);
+}
Modified: trunk/src/project.h
===================================================================
--- trunk/src/project.h 2007-01-17 17:42:23 UTC (rev 1199)
+++ trunk/src/project.h 2007-01-17 23:44:08 UTC (rev 1200)
@@ -38,7 +38,7 @@
gchar *executable; // name of the project executable
// ... // fields for build process(run arguments and so on) should be added
-
+ gchar **file_patterns; // array of filename extension patterns
};
Modified: trunk/src/utils.c
===================================================================
--- trunk/src/utils.c 2007-01-17 17:42:23 UTC (rev 1199)
+++ trunk/src/utils.c 2007-01-17 23:44:08 UTC (rev 1200)
@@ -781,11 +781,7 @@
if (! g_file_test(dir, G_FILE_TEST_EXISTS))
{
geany_debug("creating config directory %s", dir);
-#ifdef G_OS_WIN32
- if (mkdir(dir) != 0) error_nr = errno;
-#else
- if (mkdir(dir, 0700) != 0) error_nr = errno;
-#endif
+ error_nr = utils_mkdir(dir);
}
if (error_nr == 0 && ! g_file_test(conf_file, G_FILE_TEST_EXISTS))
@@ -807,11 +803,7 @@
if (! g_file_test(filedefs_dir, G_FILE_TEST_EXISTS))
{
-#ifdef G_OS_WIN32
- if (mkdir(filedefs_dir) != 0) error_nr = errno;
-#else
- if (mkdir(filedefs_dir, 0700) != 0) error_nr = errno;
-#endif
+ error_nr = utils_mkdir(filedefs_dir);
}
if (error_nr == 0 && ! g_file_test(filedefs_readme, G_FILE_TEST_EXISTS))
{
@@ -833,11 +825,7 @@
if (! g_file_test(templates_dir, G_FILE_TEST_EXISTS))
{
-#ifdef G_OS_WIN32
- if (mkdir(templates_dir) != 0) error_nr = errno;
-#else
- if (mkdir(templates_dir, 0700) != 0) error_nr = errno;
-#endif
+ error_nr = utils_mkdir(templates_dir);
}
if (error_nr == 0 && ! g_file_test(templates_readme, G_FILE_TEST_EXISTS))
{
@@ -1481,3 +1469,15 @@
}
+gint utils_mkdir(const gchar *path)
+{
+ if (path == NULL || strlen(path) == 0)
+ return EFAULT;
+
+#ifdef G_OS_WIN32
+ if (mkdir(path) != 0) return errno;
+#else
+ if (mkdir(path, 0700) != 0) return errno;
+#endif
+ return 0;
+}
Modified: trunk/src/utils.h
===================================================================
--- trunk/src/utils.h 2007-01-17 17:42:23 UTC (rev 1199)
+++ trunk/src/utils.h 2007-01-17 23:44:08 UTC (rev 1200)
@@ -154,4 +154,6 @@
* it will also be freed, the list should be ended with NULL */
void utils_free_pointers(gpointer first, ...);
+gint utils_mkdir(const gchar *path);
+
#endif
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
More information about the Commits
mailing list