[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

gEDA-cvs: pcb.git: branch: master updated (a3b303c83ceb535e6068623b77eb10b14c0ca97a)



The branch, master has been updated
       via  a3b303c83ceb535e6068623b77eb10b14c0ca97a (commit)
       via  ba4c4e33a07491a0b1952d600f4166c89f4b54ab (commit)
      from  6762885654463db6b39e6a6dfbc1911d196146fc (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.


=========
 Summary
=========

 src/hid/gtk/gtkhid-main.c    |    3 +
 src/hid/gtk/gui-top-window.c |  299 +++++++++++++++++++++++++-----------------
 src/hid/gtk/gui.h            |    5 +-
 3 files changed, 188 insertions(+), 119 deletions(-)


=================
 Commit Messages
=================

commit a3b303c83ceb535e6068623b77eb10b14c0ca97a
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Commit: Peter Clifton <pcjc2@xxxxxxxxx>

    hid/gtk: Update file-changed notification bar to match gedit a bit more
    
      1. Add a stock "refresh" image to the "Reload" button.
      2. Change the message text when the board has modifications.
      3. Reload without further prompting if the user presses "Reload",
         even if the board is modified. (We already warned them due to 2.)

:100644 100644 e598d46... 97746ad... M	src/hid/gtk/gui-top-window.c

commit ba4c4e33a07491a0b1952d600f4166c89f4b54ab
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Commit: Peter Clifton <pcjc2@xxxxxxxxx>

    hid/gtk: Reimplement file-change monitor without GFileMonitor
    
    I must have had a brain-fail when I hooked up setting up the file-changed
    monitor in the function which sets the window title.
    NB: That also gets called after every menu operation!
    
    A better place to hook up the monitor would be ghid_sync_with_new_layout(),
    however changing this alone revealed another issue - we would get notified
    for changes WE make to the files. We were avoiding those events as the
    file-monitor was being reset before it could pop up, at the end of the
    menu action which invoked the save).
    
    However - due to a race condition bug in GLib / GIO, we would sometimes
    see change notify events for changes we made, even when we hooked up
    the GFileMonitor AFTER having saved (and synced) our changes to disk.
    
    Rather than attempt to work around this bug, implement the file-change
    notification in a much more simple way - look at the file mtime when we
    update the layout, and at each time the mouse pointer enters the main
    window. FWIW, this is how gedit currently achieves the same feature.

:100644 100644 89d50be... a855aa7... M	src/hid/gtk/gtkhid-main.c
:100644 100644 73bada5... e598d46... M	src/hid/gtk/gui-top-window.c
:100644 100644 dfed2c6... 6de2578... M	src/hid/gtk/gui.h

=========
 Changes
=========

commit a3b303c83ceb535e6068623b77eb10b14c0ca97a
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Commit: Peter Clifton <pcjc2@xxxxxxxxx>

    hid/gtk: Update file-changed notification bar to match gedit a bit more
    
      1. Add a stock "refresh" image to the "Reload" button.
      2. Change the message text when the board has modifications.
      3. Reload without further prompting if the user presses "Reload",
         even if the board is modified. (We already warned them due to 2.)

diff --git a/src/hid/gtk/gui-top-window.c b/src/hid/gtk/gui-top-window.c
index e598d46..97746ad 100644
--- a/src/hid/gtk/gui-top-window.c
+++ b/src/hid/gtk/gui-top-window.c
@@ -220,7 +220,7 @@ info_bar_response_cb (GtkInfoBar *info_bar,
   _gui->info_bar = NULL;
 
   if (response_id == GTK_RESPONSE_ACCEPT)
-    hid_actionl ("LoadFrom", "revert", "none", NULL);
+    RevertPCB ();
 }
 
 static void
@@ -234,39 +234,49 @@ close_file_modified_externally_prompt (void)
 static void
 show_file_modified_externally_prompt (void)
 {
+  GtkWidget *button;
+  GtkWidget *button_image;
   GtkWidget *icon;
   GtkWidget *label;
   GtkWidget *content_area;
   char *file_path_utf8;
+  char *secondary_text;
   char *markup;
 
   close_file_modified_externally_prompt ();
 
-  ghidgui->info_bar = gtk_info_bar_new_with_buttons (_("Reload"),
-                                                  GTK_RESPONSE_ACCEPT,
-                                                  GTK_STOCK_CANCEL,
-                                                  GTK_RESPONSE_CANCEL,
-                                                  NULL);
+  ghidgui->info_bar = gtk_info_bar_new ();
+
+  button = gtk_info_bar_add_button (GTK_INFO_BAR (ghidgui->info_bar),
+                                    _("Reload"),
+                                    GTK_RESPONSE_ACCEPT);
+  button_image = gtk_image_new_from_stock (GTK_STOCK_REFRESH,
+                                           GTK_ICON_SIZE_BUTTON);
+  gtk_button_set_image (GTK_BUTTON (button), button_image);
+
+  gtk_info_bar_add_button (GTK_INFO_BAR (ghidgui->info_bar),
+                           GTK_STOCK_CANCEL,
+                           GTK_RESPONSE_CANCEL);
+  gtk_info_bar_set_message_type (GTK_INFO_BAR (ghidgui->info_bar),
+                                 GTK_MESSAGE_WARNING);
   gtk_box_pack_start (GTK_BOX (ghidgui->vbox_middle),
                       ghidgui->info_bar, FALSE, FALSE, 0);
   gtk_box_reorder_child (GTK_BOX (ghidgui->vbox_middle), ghidgui->info_bar, 0);
 
-  gtk_info_bar_set_message_type (GTK_INFO_BAR (ghidgui->info_bar),
-                                 GTK_MESSAGE_WARNING);
 
   g_signal_connect (ghidgui->info_bar, "response",
                     G_CALLBACK (info_bar_response_cb), ghidgui);
 
   file_path_utf8 = g_filename_to_utf8 (PCB->Filename, -1, NULL, NULL, NULL);
-  markup =
-    g_markup_printf_escaped (_("<b>The file %s has changed on disk</b>\n"
-                               "\n"
-                               "Do you want to reload the file?"),
-                             file_path_utf8);
+
+  secondary_text = PCB->Changed ? "Do you want to drop your changes and reload the file?" :
+                                  "Do you want to reload the file?";
+
+  markup =  g_markup_printf_escaped (_("<b>The file %s has changed on disk</b>\n\n%s"),
+                                     file_path_utf8, secondary_text);
   g_free (file_path_utf8);
 
-  content_area =
-    gtk_info_bar_get_content_area (GTK_INFO_BAR (ghidgui->info_bar));
+  content_area = gtk_info_bar_get_content_area (GTK_INFO_BAR (ghidgui->info_bar));
 
   icon = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING,
                                    GTK_ICON_SIZE_DIALOG);

commit ba4c4e33a07491a0b1952d600f4166c89f4b54ab
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Commit: Peter Clifton <pcjc2@xxxxxxxxx>

    hid/gtk: Reimplement file-change monitor without GFileMonitor
    
    I must have had a brain-fail when I hooked up setting up the file-changed
    monitor in the function which sets the window title.
    NB: That also gets called after every menu operation!
    
    A better place to hook up the monitor would be ghid_sync_with_new_layout(),
    however changing this alone revealed another issue - we would get notified
    for changes WE make to the files. We were avoiding those events as the
    file-monitor was being reset before it could pop up, at the end of the
    menu action which invoked the save).
    
    However - due to a race condition bug in GLib / GIO, we would sometimes
    see change notify events for changes we made, even when we hooked up
    the GFileMonitor AFTER having saved (and synced) our changes to disk.
    
    Rather than attempt to work around this bug, implement the file-change
    notification in a much more simple way - look at the file mtime when we
    update the layout, and at each time the mouse pointer enters the main
    window. FWIW, this is how gedit currently achieves the same feature.

diff --git a/src/hid/gtk/gtkhid-main.c b/src/hid/gtk/gtkhid-main.c
index 89d50be..a855aa7 100644
--- a/src/hid/gtk/gtkhid-main.c
+++ b/src/hid/gtk/gtkhid-main.c
@@ -2170,6 +2170,9 @@ hid_gtk_init ()
   ghid_hid.flush_debug_draw         = ghid_flush_debug_draw;
   ghid_hid.finish_debug_draw        = ghid_finish_debug_draw;
 
+  ghid_hid.notify_save_pcb          = ghid_notify_save_pcb;
+  ghid_hid.notify_filename_changed  = ghid_notify_filename_changed;
+
   hid_register_hid (&ghid_hid);
 #include "gtk_lists.h"
 }
diff --git a/src/hid/gtk/gui-top-window.c b/src/hid/gtk/gui-top-window.c
index 73bada5..e598d46 100644
--- a/src/hid/gtk/gui-top-window.c
+++ b/src/hid/gtk/gui-top-window.c
@@ -211,6 +211,126 @@ top_window_configure_event_cb (GtkWidget * widget, GdkEventConfigure * ev,
   return FALSE;
 }
 
+static void
+info_bar_response_cb (GtkInfoBar *info_bar,
+                      gint        response_id,
+                      GhidGui    *_gui)
+{
+  gtk_widget_destroy (_gui->info_bar);
+  _gui->info_bar = NULL;
+
+  if (response_id == GTK_RESPONSE_ACCEPT)
+    hid_actionl ("LoadFrom", "revert", "none", NULL);
+}
+
+static void
+close_file_modified_externally_prompt (void)
+{
+  if (ghidgui->info_bar != NULL)
+    gtk_widget_destroy (ghidgui->info_bar);
+  ghidgui->info_bar = NULL;
+}
+
+static void
+show_file_modified_externally_prompt (void)
+{
+  GtkWidget *icon;
+  GtkWidget *label;
+  GtkWidget *content_area;
+  char *file_path_utf8;
+  char *markup;
+
+  close_file_modified_externally_prompt ();
+
+  ghidgui->info_bar = gtk_info_bar_new_with_buttons (_("Reload"),
+                                                  GTK_RESPONSE_ACCEPT,
+                                                  GTK_STOCK_CANCEL,
+                                                  GTK_RESPONSE_CANCEL,
+                                                  NULL);
+  gtk_box_pack_start (GTK_BOX (ghidgui->vbox_middle),
+                      ghidgui->info_bar, FALSE, FALSE, 0);
+  gtk_box_reorder_child (GTK_BOX (ghidgui->vbox_middle), ghidgui->info_bar, 0);
+
+  gtk_info_bar_set_message_type (GTK_INFO_BAR (ghidgui->info_bar),
+                                 GTK_MESSAGE_WARNING);
+
+  g_signal_connect (ghidgui->info_bar, "response",
+                    G_CALLBACK (info_bar_response_cb), ghidgui);
+
+  file_path_utf8 = g_filename_to_utf8 (PCB->Filename, -1, NULL, NULL, NULL);
+  markup =
+    g_markup_printf_escaped (_("<b>The file %s has changed on disk</b>\n"
+                               "\n"
+                               "Do you want to reload the file?"),
+                             file_path_utf8);
+  g_free (file_path_utf8);
+
+  content_area =
+    gtk_info_bar_get_content_area (GTK_INFO_BAR (ghidgui->info_bar));
+
+  icon = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING,
+                                   GTK_ICON_SIZE_DIALOG);
+  gtk_box_pack_start (GTK_BOX (content_area),
+                      icon, FALSE, FALSE, 0);
+
+  label = gtk_label_new ("");
+  gtk_box_pack_start (GTK_BOX (content_area),
+                      label, TRUE, TRUE, 6);
+
+  gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+  gtk_label_set_markup (GTK_LABEL (label), markup);
+  g_free (markup);
+
+  gtk_misc_set_alignment (GTK_MISC (label), 0., 0.5);
+
+  gtk_widget_show_all (ghidgui->info_bar);
+}
+
+static bool
+check_externally_modified (void)
+{
+  GFile *file;
+  GFileInfo *info;
+  GTimeVal timeval;
+
+  /* Treat zero time as a flag to indicate we've not got an mtime yet */
+  if (PCB->Filename == NULL ||
+      (ghidgui->our_mtime.tv_sec == 0 &&
+       ghidgui->our_mtime.tv_usec == 0))
+    return false;
+
+  file = g_file_new_for_path (PCB->Filename);
+  info = g_file_query_info (file, G_FILE_ATTRIBUTE_TIME_MODIFIED,
+                            G_FILE_QUERY_INFO_NONE, NULL, NULL);
+  g_object_unref (file);
+
+  if (info == NULL ||
+      !g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_TIME_MODIFIED))
+    return false;
+
+  g_file_info_get_modification_time (info, &timeval); //&ghidgui->last_seen_mtime);
+  g_object_unref (info);
+
+  /* Ignore when the file on disk is the same age as when we last looked */
+  if (timeval.tv_sec == ghidgui->last_seen_mtime.tv_sec &&
+      timeval.tv_usec == ghidgui->last_seen_mtime.tv_usec)
+    return false;
+
+  ghidgui->last_seen_mtime = timeval;
+
+  return (ghidgui->last_seen_mtime.tv_sec > ghidgui->our_mtime.tv_sec) ||
+         (ghidgui->last_seen_mtime.tv_sec == ghidgui->our_mtime.tv_sec &&
+         ghidgui->last_seen_mtime.tv_usec > ghidgui->our_mtime.tv_usec);
+}
+
+static gboolean
+top_window_enter_cb (GtkWidget *widget, GdkEvent  *event, GHidPort *port)
+{
+  if (check_externally_modified ())
+    show_file_modified_externally_prompt ();
+
+  return FALSE;
+}
 
 /*! \brief Menu action callback function
  *  \par Function Description
@@ -262,6 +382,34 @@ void ghid_hotkey_cb (int which)
                   (gpointer) ghid_hotkey_actions[which].node);
 }
 
+static void
+update_board_mtime_from_disk (void)
+{
+  GFile *file;
+  GFileInfo *info;
+
+  ghidgui->our_mtime.tv_sec = 0;
+  ghidgui->our_mtime.tv_usec = 0;
+  ghidgui->last_seen_mtime = ghidgui->our_mtime;
+
+  if (PCB->Filename == NULL)
+    return;
+
+  file = g_file_new_for_path (PCB->Filename);
+  info = g_file_query_info (file, G_FILE_ATTRIBUTE_TIME_MODIFIED,
+                            G_FILE_QUERY_INFO_NONE, NULL, NULL);
+  g_object_unref (file);
+
+  if (info == NULL ||
+      !g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_TIME_MODIFIED))
+    return;
+
+  g_file_info_get_modification_time (info, &ghidgui->our_mtime);
+  g_object_unref (info);
+
+  ghidgui->last_seen_mtime = ghidgui->our_mtime;
+}
+
   /* Sync toggle states that were saved with the layout and notify the
      |  config code to update Settings values it manages.
    */
@@ -277,6 +425,27 @@ ghid_sync_with_new_layout (void)
 
   ghid_window_set_name_label (PCB->Name);
   ghid_set_status_line_label ();
+  close_file_modified_externally_prompt ();
+  update_board_mtime_from_disk ();
+}
+
+void
+ghid_notify_save_pcb (const char *filename, bool done)
+{
+  /* Do nothing if it is not the active PCB file that is being saved.
+   */
+  if (PCB->Filename == NULL || strcmp (filename, PCB->Filename) != 0)
+    return;
+
+  if (done)
+    update_board_mtime_from_disk ();
+}
+
+void
+ghid_notify_filename_changed (void)
+{
+  /* Pick up the mtime of the new PCB file */
+  update_board_mtime_from_disk ();
 }
 
 /* ---------------------------------------------------------------------------
@@ -467,119 +636,6 @@ ghid_remove_accel_groups (GtkWindow *window, GhidGui *gui)
                (GHID_ROUTE_STYLE_SELECTOR (gui->route_style_selector)));
 }
 
-static void
-info_bar_response_cb (GtkInfoBar *info_bar,
-                      gint        response_id,
-                      gpointer    user_data)
-{
-  GhidGui *_gui = (GhidGui *)user_data;
-
-  gtk_widget_destroy (_gui->info_bar);
-  _gui->info_bar = NULL;
-
-  if (response_id == GTK_RESPONSE_ACCEPT)
-    hid_actionl ("LoadFrom", "revert", "none", NULL);
-}
-
-static void
-file_changed_cb (GFileMonitor     *monitor,
-                 GFile            *file,
-                 GFile            *other_file,
-                 GFileMonitorEvent event_type,
-                 gpointer          user_data)
-{
-  GhidGui *_gui = (GhidGui *)user_data;
-  GtkWidget *icon;
-  GtkWidget *label;
-  GtkWidget *content_area;
-  char *file_path;
-  char *file_path_utf8;
-  char *markup;
-
-  if (event_type != G_FILE_MONITOR_EVENT_CHANGED)
-    return;
-
-  /* File has changed on disk */
-
-  if (_gui->info_bar)
-    gtk_widget_destroy (_gui->info_bar);
-
-  _gui->info_bar = gtk_info_bar_new_with_buttons (_("Reload"),
-                                                  GTK_RESPONSE_ACCEPT,
-                                                  GTK_STOCK_CANCEL,
-                                                  GTK_RESPONSE_CANCEL,
-                                                  NULL);
-  gtk_box_pack_start (GTK_BOX (_gui->vbox_middle),
-                      _gui->info_bar, FALSE, FALSE, 0);
-  gtk_box_reorder_child (GTK_BOX (_gui->vbox_middle), _gui->info_bar, 0);
-
-  gtk_info_bar_set_message_type (GTK_INFO_BAR (_gui->info_bar),
-                                 GTK_MESSAGE_WARNING);
-
-  g_signal_connect (_gui->info_bar, "response",
-                    G_CALLBACK (info_bar_response_cb), _gui);
-
-  file_path = g_file_get_path (file);
-  file_path_utf8 = g_filename_to_utf8 (file_path, -1, NULL, NULL, NULL);
-  g_free (file_path);
-  markup =
-    g_markup_printf_escaped (_("<b>The file %s has changed on disk</b>\n"
-                               "\n"
-                               "Do you want to reload the file?"),
-                             file_path_utf8);
-  g_free (file_path_utf8);
-
-  content_area =
-    gtk_info_bar_get_content_area (GTK_INFO_BAR (_gui->info_bar));
-
-  icon = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING,
-                                   GTK_ICON_SIZE_DIALOG);
-  gtk_box_pack_start (GTK_BOX (content_area),
-                      icon, FALSE, FALSE, 0);
-
-  label = gtk_label_new ("");
-  gtk_box_pack_start (GTK_BOX (content_area),
-                      label, TRUE, TRUE, 6);
-
-  gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
-  gtk_label_set_markup (GTK_LABEL (label), markup);
-  g_free (markup);
-
-  gtk_misc_set_alignment (GTK_MISC (label), 0., 0.5);
-
-  gtk_widget_show_all (_gui->info_bar);
-}
-
-static void
-connect_file_change_monitor (GhidGui *_gui, char *filename)
-{
-  GFile *file;
-
-  if (_gui->file_monitor != NULL)
-    g_object_unref (_gui->file_monitor);
-  _gui->file_monitor = NULL;
-
-  if (_gui->info_bar != NULL)
-    gtk_widget_destroy (_gui->info_bar);
-  _gui->info_bar = NULL;
-
-  if (filename == NULL)
-    return;
-
-  file = g_file_new_for_path (filename);
-
-  /* XXX: Could hook up more error handling for g_file_monitor_file */
-  _gui->file_monitor = g_file_monitor_file (file,
-                                            G_FILE_MONITOR_NONE,
-                                            NULL,
-                                            NULL);
-  g_object_unref (file);
-
-  g_signal_connect (_gui->file_monitor, "changed",
-                    G_CALLBACK (file_changed_cb), _gui);
-}
-
-
 /* Refreshes the window title bar and sets the PCB name to the
  * window title bar or to a seperate label
  */
@@ -608,11 +664,6 @@ ghid_window_set_name_label (gchar * name)
   gtk_window_set_title (GTK_WINDOW (gport->top_window), str);
   g_free (str);
   g_free (filename);
-
-  if (PCB->Filename && *PCB->Filename)
-    connect_file_change_monitor (ghidgui, PCB->Filename);
-  else
-    connect_file_change_monitor (ghidgui, NULL);
 }
 
 static void
@@ -1319,6 +1370,8 @@ ghid_build_pcb_top_window (void)
 		    port);
   g_signal_connect (G_OBJECT (gport->top_window), "configure_event",
 		    G_CALLBACK (top_window_configure_event_cb), port);
+  g_signal_connect (gport->top_window, "enter-notify-event",
+                    G_CALLBACK (top_window_enter_cb), port);
   g_signal_connect (G_OBJECT (gport->drawing_area), "configure_event",
 		    G_CALLBACK (ghid_port_drawing_area_configure_event_cb),
 		    port);
diff --git a/src/hid/gtk/gui.h b/src/hid/gtk/gui.h
index dfed2c6..6de2578 100644
--- a/src/hid/gtk/gui.h
+++ b/src/hid/gtk/gui.h
@@ -115,7 +115,8 @@ typedef struct
   GtkWidget *vbox_middle;
 
   GtkWidget *info_bar;
-  GFileMonitor *file_monitor;
+  GTimeVal our_mtime;
+  GTimeVal last_seen_mtime;
 
   GtkWidget *h_range, *v_range;
   GtkObject *h_adjustment, *v_adjustment;
@@ -338,6 +339,8 @@ int ghid_drc_window_throw_dialog (void);
 
 /* In gui-top-window.c  */
 void ghid_update_toggle_flags (void);
+void ghid_notify_save_pcb (const char *file, bool done);
+void ghid_notify_filename_changed (void);
 void ghid_install_accel_groups (GtkWindow *window, GhidGui *gui);
 void ghid_remove_accel_groups (GtkWindow *window, GhidGui *gui);
 




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