Branch: refs/heads/master Author: Jiří Techet techet@gmail.com Committer: GitHub noreply@github.com Date: Fri, 13 May 2022 00:19:35 UTC Commit: 4b573b7a402347cb6b74c07057d862b66959fa2a https://github.com/geany/geany/commit/4b573b7a402347cb6b74c07057d862b66959fa...
Log Message: ----------- Merge pull request #3042 from techee/project_create2
Improve user experience when creating new projects, attempt 2
Modified Paths: -------------- data/geany.glade doc/geany.txt src/callbacks.c src/callbacks.h src/keybindings.c src/keybindings.h src/keyfile.c src/plugindata.h src/project.c src/project.h src/ui_utils.c src/ui_utils.h
Modified: data/geany.glade 17 lines changed, 17 insertions(+), 0 deletions(-) =================================================================== @@ -704,6 +704,12 @@ <property name="stock">gtk-find</property> <property name="icon_size">1</property> </object> + <object class="GtkImage" id="image7"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="stock">gtk-new</property> + <property name="icon-size">1</property> + </object> <object class="GtkListStore" id="indent_mode_list"> <columns> <!-- column-name item --> @@ -7897,6 +7903,17 @@ <signal name="activate" handler="on_project_new1_activate" swapped="no"/> </object> </child> + <child> + <object class="GtkImageMenuItem" id="project_new_from_folder1"> + <property name="label" translatable="yes">New from _Folder...</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="use_underline">True</property> + <property name="image">image7</property> + <property name="use_stock">False</property> + <signal name="activate" handler="on_project_new_from_folder1_activate" swapped="no"/> + </object> + </child> <child> <object class="GtkImageMenuItem" id="project_open1"> <property name="label" translatable="yes">_Open...</property>
Modified: doc/geany.txt 37 lines changed, 29 insertions(+), 8 deletions(-) =================================================================== @@ -2776,14 +2776,35 @@ The project menu items are detailed below. New project ^^^^^^^^^^^
-To create a new project, fill in the *Name* field. By default this -will setup a new project file ``~/projects/name.geany``. Usually it's -best to store all your project files in the same directory (they are -independent of any source directory trees). - -The Base path text field is setup to use ``~/projects/name``. This -can safely be set to any existing path -- it will not touch the file -structure contained in it. +There are two ways of creating new projects, either by using +*Project->New* menu item or by using *Project->New from Folder* menu +item. + +New + This method is more suitable for creating new, empty projects from + scratch at the default location without having any existing sources. + + To create a new project, fill in the *Name* field. By default this + will setup a new project file ``~/projects/name/name.geany``. + + The *Base path* text field is setup to use ``~/projects/name``. This + can safely be set to any existing path -- it will not touch the file + structure contained in it. + +New from Folder + This method is more suitable when there is already some folder + containing source files for which you want to create a new project. + + When using this method, Geany first opens a directory selection + dialog to select the folder containing the sources, and the + *Base path* field is set to that value. + + Afterwards, Geany shows the same dialog as the *Project->New* + method but already pre-filled with the values based on the + *Base path* selection. The *Name* field is filled with the folder + name, the *Filename* field is filled with + ``base_path/name.geany`` and the *Base path* field is filled with + the path specified in the previous dialog.
Project properties
Modified: src/callbacks.c 8 lines changed, 7 insertions(+), 1 deletions(-) =================================================================== @@ -1387,7 +1387,13 @@ void on_previous_message1_activate(GtkMenuItem *menuitem, gpointer user_data)
void on_project_new1_activate(GtkMenuItem *menuitem, gpointer user_data) { - project_new(); + project_new(FALSE); +} + + +void on_project_new_from_folder1_activate(GtkMenuItem *menuitem, gpointer user_data) +{ + project_new(TRUE); }
Modified: src/callbacks.h 2 lines changed, 2 insertions(+), 0 deletions(-) =================================================================== @@ -144,6 +144,8 @@ void on_next_message1_activate(GtkMenuItem *menuitem, gpointer user_data);
void on_project_new1_activate(GtkMenuItem *menuitem, gpointer user_data);
+void on_project_new_from_folder1_activate(GtkMenuItem *menuitem, gpointer user_data); + void on_project_open1_activate(GtkMenuItem *menuitem, gpointer user_data);
void on_project_close1_activate(GtkMenuItem *menuitem, gpointer user_data);
Modified: src/keybindings.c 5 lines changed, 5 insertions(+), 0 deletions(-) =================================================================== @@ -366,6 +366,8 @@ static void init_default_kb(void)
add_kb(group, GEANY_KEYS_PROJECT_NEW, NULL, 0, 0, "project_new", _("New"), "project_new1"); + add_kb(group, GEANY_KEYS_PROJECT_NEW_FROM_FOLDER, NULL, + 0, 0, "project_new_from_folder", _("New from Folder"), "project_new_from_folder1"); add_kb(group, GEANY_KEYS_PROJECT_OPEN, NULL, 0, 0, "project_open", _("Open"), "project_open1"); add_kb(group, GEANY_KEYS_PROJECT_PROPERTIES, NULL, @@ -1502,6 +1504,9 @@ static gboolean cb_func_project_action(guint key_id) case GEANY_KEYS_PROJECT_NEW: on_project_new1_activate(NULL, NULL); break; + case GEANY_KEYS_PROJECT_NEW_FROM_FOLDER: + on_project_new_from_folder1_activate(NULL, NULL); + break; case GEANY_KEYS_PROJECT_OPEN: on_project_open1_activate(NULL, NULL); break;
Modified: src/keybindings.h 2 lines changed, 2 insertions(+), 0 deletions(-) =================================================================== @@ -277,6 +277,8 @@ enum GeanyKeyBindingID * @since 1.34 (API 238) */ GEANY_KEYS_FILE_RELOAD_ALL, /**< Keybinding. * @since 1.38 (API 240) */ + GEANY_KEYS_PROJECT_NEW_FROM_FOLDER, /**< Keybinding. + * @since 1.39 (API 243) */ GEANY_KEYS_COUNT /* must not be used by plugins */ };
Modified: src/keyfile.c 2 lines changed, 1 insertions(+), 1 deletions(-) =================================================================== @@ -824,7 +824,7 @@ static void load_dialog_prefs(GKeyFile *config) prefs.confirm_exit = utils_get_setting_boolean(config, PACKAGE, "pref_main_confirm_exit", FALSE); prefs.suppress_status_messages = utils_get_setting_boolean(config, PACKAGE, "pref_main_suppress_status_messages", FALSE); prefs.load_session = utils_get_setting_boolean(config, PACKAGE, "pref_main_load_session", TRUE); - project_prefs.project_file_in_basedir = utils_get_setting_boolean(config, PACKAGE, "pref_main_project_file_in_basedir", FALSE); + project_prefs.project_file_in_basedir = utils_get_setting_boolean(config, PACKAGE, "pref_main_project_file_in_basedir", TRUE); prefs.save_winpos = utils_get_setting_boolean(config, PACKAGE, "pref_main_save_winpos", TRUE); prefs.save_wingeom = utils_get_setting_boolean(config, PACKAGE, "pref_main_save_wingeom", prefs.save_winpos); prefs.beep_on_errors = utils_get_setting_boolean(config, PACKAGE, "beep_on_errors", TRUE);
Modified: src/plugindata.h 2 lines changed, 1 insertions(+), 1 deletions(-) =================================================================== @@ -57,7 +57,7 @@ G_BEGIN_DECLS * @warning You should not test for values below 200 as previously * @c GEANY_API_VERSION was defined as an enum value, not a macro. */ -#define GEANY_API_VERSION 243 +#define GEANY_API_VERSION 244
/* hack to have a different ABI when built with different GTK major versions * because loading plugins linked to a different one leads to crashes.
Modified: src/project.c 105 lines changed, 85 insertions(+), 20 deletions(-) =================================================================== @@ -83,6 +83,8 @@ static gboolean update_config(const PropertyDialogElements *e, gboolean new_proj static void on_file_save_button_clicked(GtkButton *button, PropertyDialogElements *e); static gboolean load_config(const gchar *filename); static gboolean write_config(void); +static void update_new_project_dlg(GtkEditable *editable, PropertyDialogElements *e, + const gchar *base_p); static void on_name_entry_changed(GtkEditable *editable, PropertyDialogElements *e); static void on_entries_changed(GtkEditable *editable, PropertyDialogElements *e); static void on_radio_long_line_custom_toggled(GtkToggleButton *radio, GtkWidget *spin_long_line); @@ -141,7 +143,7 @@ static gboolean handle_current_session(void) /* TODO: this should be ported to Glade like the project preferences dialog, * then we can get rid of the PropertyDialogElements struct altogether as * widgets pointers can be accessed through ui_lookup_widget(). */ -void project_new(void) +void project_new(gboolean from_folder) { GtkWidget *vbox; GtkWidget *table; @@ -150,8 +152,28 @@ void project_new(void) GtkWidget *bbox; GtkWidget *label; gchar *tooltip; + gchar *base_path = NULL; PropertyDialogElements e = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, FALSE };
+ if (from_folder) + { + GeanyDocument *doc = document_get_current(); + gchar *start_path; + + if (doc && doc->file_name) + start_path = g_path_get_dirname(doc->file_name); + else if (!EMPTY(local_prefs.project_file_path)) + start_path = g_strdup(local_prefs.project_file_path); + else + start_path = utils_get_utf8_from_locale(g_get_home_dir()); + + base_path = ui_get_project_directory(start_path); + g_free(start_path); + + if (!base_path) + return; + } + e.dialog = gtk_dialog_new_with_buttons(_("New Project"), GTK_WINDOW(main_widgets.window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, NULL); @@ -185,7 +207,7 @@ void project_new(void) e.file_name = gtk_entry_new(); gtk_entry_set_activates_default(GTK_ENTRY(e.file_name), TRUE); ui_entry_add_clear_icon(GTK_ENTRY(e.file_name)); - gtk_entry_set_width_chars(GTK_ENTRY(e.file_name), 30); + gtk_entry_set_width_chars(GTK_ENTRY(e.file_name), 40); tooltip = g_strdup_printf( _("Path of the file representing the project and storing its settings. " "It should normally have the "%s" extension."), "."GEANY_PROJECT_EXT); @@ -218,13 +240,20 @@ void project_new(void)
gtk_box_pack_start(GTK_BOX(vbox), table, TRUE, TRUE, 0);
- /* signals */ - g_signal_connect(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); + if (base_path) + { + update_new_project_dlg(GTK_EDITABLE(e.name), &e, base_path); + g_free(base_path); + } + else + { + /* signals */ + g_signal_connect(e.name, "changed", G_CALLBACK(on_name_entry_changed), &e); + g_signal_connect(e.file_name, "changed", G_CALLBACK(on_entries_changed), &e); + g_signal_connect(e.base_path, "changed", G_CALLBACK(on_entries_changed), &e);
- g_signal_connect(e.file_name, "changed", G_CALLBACK(on_entries_changed), &e); - g_signal_connect(e.base_path, "changed", G_CALLBACK(on_entries_changed), &e); + update_new_project_dlg(GTK_EDITABLE(e.name), &e, NULL); + }
gtk_widget_show_all(e.dialog); run_new_dialog(&e); @@ -950,35 +979,64 @@ static void on_file_save_button_clicked(GtkButton *button, PropertyDialogElement }
-/* sets the project base path and the project file name according to the project name */ -static void on_name_entry_changed(GtkEditable *editable, PropertyDialogElements *e) +/* sets the New Project dialog entries according to the base path or project name */ +static void update_new_project_dlg(GtkEditable *editable, PropertyDialogElements *e, + const gchar *base_p) { gchar *base_path; gchar *file_name; - gchar *name; - const gchar *project_dir = local_prefs.project_file_path; + gchar *project_dir = NULL;
if (e->entries_modified) return;
- name = gtk_editable_get_chars(editable, 0, -1); - if (!EMPTY(name)) + if (!EMPTY(local_prefs.project_file_path)) + project_dir = g_strdup(local_prefs.project_file_path); + else { - base_path = g_strconcat(project_dir, G_DIR_SEPARATOR_S, - name, G_DIR_SEPARATOR_S, NULL); + GeanyDocument *doc = document_get_current(); + + if (doc && doc->file_name) + project_dir = g_path_get_dirname(doc->file_name); + else + project_dir = utils_get_utf8_from_locale(g_get_home_dir()); + } + + if (!EMPTY(base_p)) + { + gchar *name = g_path_get_basename(base_p); + + base_path = g_strdup(base_p); + gtk_entry_set_text(GTK_ENTRY(e->name), name); if (project_prefs.project_file_in_basedir) - file_name = g_strconcat(project_dir, G_DIR_SEPARATOR_S, name, G_DIR_SEPARATOR_S, + file_name = g_strconcat(base_path, G_DIR_SEPARATOR_S, name, "." GEANY_PROJECT_EXT, NULL); else file_name = g_strconcat(project_dir, G_DIR_SEPARATOR_S, name, "." GEANY_PROJECT_EXT, NULL); + g_free(name); } else { - base_path = g_strconcat(project_dir, G_DIR_SEPARATOR_S, NULL); - file_name = g_strconcat(project_dir, G_DIR_SEPARATOR_S, NULL); + gchar *name = gtk_editable_get_chars(editable, 0, -1); + if (!EMPTY(name)) + { + base_path = g_strconcat(project_dir, G_DIR_SEPARATOR_S, + name, G_DIR_SEPARATOR_S, NULL); + if (project_prefs.project_file_in_basedir) + file_name = g_strconcat(project_dir, G_DIR_SEPARATOR_S, name, G_DIR_SEPARATOR_S, + name, "." GEANY_PROJECT_EXT, NULL); + else + file_name = g_strconcat(project_dir, G_DIR_SEPARATOR_S, + name, "." GEANY_PROJECT_EXT, NULL); + } + else + { + base_path = g_strconcat(project_dir, G_DIR_SEPARATOR_S, NULL); + file_name = g_strconcat(project_dir, G_DIR_SEPARATOR_S, NULL); + } + g_free(name); } - g_free(name);
gtk_entry_set_text(GTK_ENTRY(e->base_path), base_path); gtk_entry_set_text(GTK_ENTRY(e->file_name), file_name); @@ -987,6 +1045,13 @@ static void on_name_entry_changed(GtkEditable *editable, PropertyDialogElements
g_free(base_path); g_free(file_name); + g_free(project_dir); +} + + +static void on_name_entry_changed(GtkEditable *editable, PropertyDialogElements *e) +{ + update_new_project_dlg(editable, e, NULL); }
Modified: src/project.h 2 lines changed, 1 insertions(+), 1 deletions(-) =================================================================== @@ -66,7 +66,7 @@ void project_init(void); void project_finalize(void);
-void project_new(void); +void project_new(gboolean from_folder);
void project_open(void);
Modified: src/ui_utils.c 15 lines changed, 15 insertions(+), 0 deletions(-) =================================================================== @@ -1999,6 +1999,21 @@ static gchar *run_file_chooser(const gchar *title, GtkFileChooserAction action, #endif
+gchar *ui_get_project_directory(const gchar *path) +{ + gchar *utf8_path; + const gchar *title = _("Select Project Base Path"); + +#ifdef G_OS_WIN32 + utf8_path = win32_show_folder_dialog(ui_widgets.prefs_dialog, title, path); +#else + utf8_path = run_file_chooser(title, GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, path); +#endif + + return utf8_path; +} + + static void ui_path_box_open_clicked(GtkButton *button, gpointer user_data) { GtkFileChooserAction action = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(button), "action"));
Modified: src/ui_utils.h 2 lines changed, 2 insertions(+), 0 deletions(-) =================================================================== @@ -366,6 +366,8 @@ gint ui_encodings_combo_box_get_active_encoding(GtkComboBox *combo);
gboolean ui_encodings_combo_box_set_active_encoding(GtkComboBox *combo, gint enc);
+gchar *ui_get_project_directory(const gchar *path); + #endif /* GEANY_PRIVATE */
G_END_DECLS
-------------- This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).