[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: gEDA-dev: [PATCH] gschem: recent files support



On Tue, Apr 17, 2007 at 07:07:38AM +0100, Peter TB Brett wrote:
> 1. GLIB_CHECK_VERSION(2,6,0) to check the version rather than using 
> GLIB_MINOR_VERSION?

Done.

> 2. I like the way you've disabled the features with a minimum number of 
> #ifdefs.

Me too.  :)

> 3. Rather than adding an extra substitution to system-gschemrc.in (and an 
> extra variable in configuration mechanism), why not delete the menu item in 
> x_menu_attach_recent_files_submenu() if GLIB < 2.6?

Done.

> 4. There should probably be comment about the magicness of that menu entry in 
> the Scheme file.

Done, the new patch is attached.

-- 
Ivan Stankovic, ivan.stankovic@fer.hr

"Protect your digital freedom and privacy, eliminate DRM, 
learn more at http://www.defectivebydesign.org/what_is_drm"
>From d46553900a7900620f5fcaec6a8f8bada80c9ce7 Mon Sep 17 00:00:00 2001
From: Ivan Stankovic <ivan.stankovic@fer.hr>
Date: Mon, 23 Apr 2007 23:27:31 +0200
Subject: [PATCH] gschem: add recent files support

Requires glib >= 2.6
---
 gschem/include/prototype.h    |    4 +
 gschem/lib/system-gschemrc.in |    2 +
 gschem/src/gschem.c           |    4 +
 gschem/src/x_menus.c          |  218 +++++++++++++++++++++++++++++++++++++++++
 gschem/src/x_window.c         |    6 +
 5 files changed, 234 insertions(+), 0 deletions(-)

diff --git a/gschem/include/prototype.h b/gschem/include/prototype.h
index 85fde2c..db46ed6 100644
--- a/gschem/include/prototype.h
+++ b/gschem/include/prototype.h
@@ -834,6 +834,10 @@ GtkWidget *get_main_popup(TOPLEVEL *w_current);
 gint do_popup(TOPLEVEL *w_current, GdkEventButton *event);
 void x_menus_sensitivity(TOPLEVEL *w_current, const char *buf, int flag);
 void x_menus_popup_sensitivity(TOPLEVEL *w_current, const char *buf, int flag);
+void x_menu_attach_recent_files_submenu(TOPLEVEL *w_current);
+void recent_files_load();
+void recent_files_save();
+void recent_files_add(const char *filename);
 /* x_multiattrib.c */
 void x_multiattrib_open (TOPLEVEL *toplevel, OBJECT *object);
 /* x_multimulti.c */
diff --git a/gschem/lib/system-gschemrc.in b/gschem/lib/system-gschemrc.in
index ae293c5..41b85ec 100644
--- a/gschem/lib/system-gschemrc.in
+++ b/gschem/lib/system-gschemrc.in
@@ -1574,6 +1574,8 @@
 	   ("Save All" 		file-save-all 		file-save-all)
 	   ("Print..." 		file-print 		file-print)
 	   ("Write image..." 	file-image 		file-image)
+;; The entry below will be removed from the menu if glib < 2.6 is detected
+	   ("Recent files"      no-action 		no-action)
 	   ("SEPARATOR"         no-action 		no-action)
 	   ("Execute Script..." file-script 		file-script)
 	   ("SEPARATOR"         no-action 		no-action)
diff --git a/gschem/src/gschem.c b/gschem/src/gschem.c
index 1af690b..11ec448 100644
--- a/gschem/src/gschem.c
+++ b/gschem/src/gschem.c
@@ -200,6 +200,10 @@ void main_prog(void *closure, int argc, char *argv[])
   }
   g_free(input_str);
 
+  /* Load recent files list. This must be done
+   * before calling x_window_setup(). */
+  recent_files_load();
+
   /* At end, complete set up of window. */
   colormap = gdk_colormap_get_system ();
   x_window_setup_colors();
diff --git a/gschem/src/x_menus.c b/gschem/src/x_menus.c
index d1fc794..e963844 100644
--- a/gschem/src/x_menus.c
+++ b/gschem/src/x_menus.c
@@ -363,3 +363,221 @@ void x_menus_popup_sensitivity (TOPLEVEL* w_current, const char *buf, int flag)
     s_log_message(_("Tried to set the sensitivity on a non-existent popup menu_item\n")); 
   }
 }
+
+#if !GLIB_CHECK_VERSION(2,6,0)
+
+/* disable recent files support */
+inline void x_menu_attach_recent_files_submenu(TOPLEVEL *w_current)
+{
+   GtkWidget *recent_menu_item;
+
+   recent_menu_item = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(
+            w_current->menubar), "File/Recent files");
+   gtk_widget_destroy(recent_menu_item);
+}
+
+inline void recent_files_load() { }
+inline void recent_files_save() { }
+inline void recent_files_add(const char *filename) { }
+
+#else
+
+/* The list of recently loaded files. */
+static GList *recent_files = NULL;
+
+#define RECENT_FILES_STORE ".gschem-recent-files"
+
+static void recent_file_clicked(gpointer filename)
+{
+   PAGE *page;
+   TOPLEVEL *w;
+
+   w = s_toplevel_new();
+   x_window_setup(w);
+   page = x_window_open_page(w, (char *)filename);
+   x_window_set_current_page(w, page);
+   s_log_message (_("New Window created [%s]\n"), (char *)filename);
+}
+
+/*! \brief Attach a submenu with filenames to the 'Recent files'
+ *         menu item.
+ *
+ *  Called from x_window_setup().
+ */
+void x_menu_attach_recent_files_submenu(TOPLEVEL *w_current)
+{
+   gulong id;
+   GtkWidget *recent_menu_item, *recent_submenu;
+
+   recent_menu_item = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(
+            w_current->menubar), "File/Recent files");
+
+   /* disconnect all unblocked signals */
+   while(1) {
+      id = g_signal_handler_find(recent_menu_item, G_SIGNAL_MATCH_UNBLOCKED,
+            0, 0, NULL, NULL, NULL);
+      if(id == 0)
+         break;
+      gtk_signal_disconnect(recent_menu_item, id);
+   }
+
+   /* remove 'q' from the menu item string; there has to be a better way to 
+    * create a menu item without a hotkey being assigned to it automatically */
+   GtkWidget *label = gtk_bin_get_child(GTK_BIN(recent_menu_item));
+   gtk_label_set_text(GTK_LABEL(label), "Recent files");
+
+   recent_submenu = gtk_menu_new();
+   GList *p = recent_files;
+   while(p) {
+      GtkWidget *tmp = gtk_menu_item_new_with_label((gchar *)p->data);
+      gtk_signal_connect_object(GTK_OBJECT(tmp), "activate",
+            GTK_SIGNAL_FUNC (recent_file_clicked),
+            p->data);
+      gtk_menu_append(GTK_MENU(recent_submenu), tmp);
+      p = g_list_next(p);
+   }
+   gtk_widget_show_all(recent_submenu);
+   gtk_menu_item_set_submenu(GTK_MENU_ITEM(recent_menu_item), recent_submenu);
+}
+
+/*! \brief Add a filename to the list of recent files.
+ */
+void recent_files_add(const char *filename)
+{
+   gchar *basename;
+   GtkWidget *recent_menu_item, *recent_submenu;
+
+   basename = g_path_get_basename(filename);
+   if(strstr(basename, "untitled_") == basename) {
+      g_free(basename);
+      return;
+   }
+
+   g_free(basename);
+
+   /* check if it is a duplicate */
+   GList *p = recent_files;
+   while(p) {
+      if(strcmp((char *)p->data, filename) == 0 )
+         return;
+      p = g_list_next(p);
+   }
+
+   filename = g_strdup(filename);
+   recent_files = g_list_prepend(recent_files, (gpointer)filename);
+
+   /* walk through all toplevels and add the filename to the recent file submenu */
+   TOPLEVEL *w = global_window_current;
+   while(w->prev)
+      w = w->prev;
+
+   while(w) {
+      if(w->menubar == NULL) {
+         w = w->next;
+         continue;
+      }
+
+      recent_menu_item = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(
+               w->menubar), "File/Recent files");
+      recent_submenu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(recent_menu_item));
+
+      GtkWidget *s = gtk_menu_item_new_with_label(filename);
+      gtk_widget_show(s);
+      gtk_menu_shell_prepend(GTK_MENU_SHELL(recent_submenu), s);
+      gtk_signal_connect_object(GTK_OBJECT(s), "activate",
+            GTK_SIGNAL_FUNC (recent_file_clicked),
+            (gpointer)filename);
+      w = w->next;
+   }
+}
+
+/*! \brief Make RECENT_FILES_STORE contain an empty file list.
+ */
+static void recent_files_create_empty()
+{
+   gchar *c;
+   const gchar * const tmp[] = { NULL };
+   GKeyFile *kf = g_key_file_new();
+   gchar *file = g_build_filename(g_get_home_dir(), RECENT_FILES_STORE, NULL);
+
+   g_key_file_set_string_list(kf, "Recent files", "Files", tmp, 0);
+   c = g_key_file_to_data(kf, NULL, NULL);
+   g_key_file_free(kf);
+
+   g_file_set_contents(file, c, -1, NULL);
+   g_free(c);
+   g_free(file);
+}
+
+/*! \brief Save the list of recent files to RECENT_FILES_STORE.
+ */
+void recent_files_save()
+{
+   gchar **files = NULL;
+   int num = 0;
+   gchar *c;
+   gchar *file = g_build_filename(g_get_home_dir(), RECENT_FILES_STORE, NULL);
+
+   GList *p = recent_files;
+   if(p == NULL) 
+      return;
+
+   while(p) {
+      files = g_realloc(files, (num + 1) * sizeof(gchar *));
+      files[num++] = (gchar *)p->data;
+      p = g_list_next(p);
+   }
+
+   GKeyFile *kf = g_key_file_new();
+
+   g_key_file_set_string_list(kf, "Recent files", "Files", 
+         (const gchar **)files, num);
+   c = g_key_file_to_data(kf, NULL, NULL);
+   g_file_set_contents(file, c, -1, NULL);
+
+   g_free(c);
+   g_free(file);
+   g_free(files);
+   g_key_file_free(kf);
+}
+
+/*! \brief Load the recent file list using data from
+ *         RECENT_FILES_STORE. 
+ *
+ *  Must be called before any other recent-files-related
+ *  functions.
+ */
+void recent_files_load()
+{
+   GKeyFile *kf = g_key_file_new();
+   gchar *file = g_build_filename(g_get_home_dir(), RECENT_FILES_STORE, NULL);
+
+again:
+   if(!g_key_file_load_from_file(kf, file, G_KEY_FILE_NONE, NULL)) {
+      /* error opening key file, create an empty one */
+      recent_files_create_empty();
+      goto again;
+   }
+
+   gsize len;
+   gchar **list = g_key_file_get_string_list(kf, "Recent files",
+         "Files", &len, NULL);
+
+   if(list == NULL) {
+      /* error reading key file, don't bother to correct;
+       * just overwrite it with an empty one */
+      recent_files_create_empty();
+      goto again;
+   }
+
+   while(len > 0) {
+      len--;
+      recent_files = g_list_prepend(recent_files, list[len]);
+   }
+
+   g_free(list);
+   g_free(file);
+   g_key_file_free(kf);
+}
+
+#endif /* GLIB_MINOR_VERSION < 6 */
diff --git a/gschem/src/x_window.c b/gschem/src/x_window.c
index 0dd7112..edf8e15 100644
--- a/gschem/src/x_window.c
+++ b/gschem/src/x_window.c
@@ -157,6 +157,8 @@ void x_window_setup (TOPLEVEL *toplevel)
 
   /* X related stuff */
   x_window_create_main (toplevel);
+
+  x_menu_attach_recent_files_submenu(toplevel);
 }
 
 /*! \todo Finish function documentation!!!
@@ -828,6 +830,7 @@ void x_window_close(TOPLEVEL *w_current)
 
   /* just closed last window, so quit */
   if (last_window) {
+    recent_files_save();
     gschem_quit();
   }
   
@@ -950,6 +953,7 @@ x_window_open_page (TOPLEVEL *toplevel, const gchar *filename)
    * it will get done in x_window_set_current_page(...)
    */
   x_pagesel_update (toplevel); /* ??? */
+  recent_files_add(filename);
 
   return page;
 }
@@ -1046,6 +1050,8 @@ x_window_save_page (TOPLEVEL *toplevel, PAGE *page, const gchar *filename)
     /* reset page CHANGED flag */
     page->CHANGED = 0;
 
+    /* update recent file list */
+    recent_files_add(filename);
   }
 
   /* log status of operation */
-- 
1.5.1



_______________________________________________
geda-dev mailing list
geda-dev@moria.seul.org
http://www.seul.org/cgi-bin/mailman/listinfo/geda-dev