]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkfilechooserentry.c
stylecontext: Do invalidation on first resize container
[~andy/gtk] / gtk / gtkfilechooserentry.c
index 4219f2f6660796b0bce6a9d1757ea00d1e733356..ce2b6cc9e7b38dbafe1c0837612541321249105d 100644 (file)
@@ -13,9 +13,7 @@
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "config.h"
@@ -45,12 +43,6 @@ struct _GtkFileChooserEntryClass
   GtkEntryClass parent_class;
 };
 
-/* Action to take when the current folder finishes loading (for explicit or automatic completion) */
-typedef enum {
-  LOAD_COMPLETE_NOTHING,
-  LOAD_COMPLETE_EXPLICIT_COMPLETION
-} LoadCompleteAction;
-
 struct _GtkFileChooserEntry
 {
   GtkEntry parent_instance;
@@ -80,8 +72,8 @@ enum
 static void     gtk_file_chooser_entry_finalize       (GObject          *object);
 static void     gtk_file_chooser_entry_dispose        (GObject          *object);
 static void     gtk_file_chooser_entry_grab_focus     (GtkWidget        *widget);
-static gboolean gtk_file_chooser_entry_key_press_event (GtkWidget *widget,
-                                                       GdkEventKey *event);
+static gboolean gtk_file_chooser_entry_tab_handler    (GtkWidget *widget,
+                                                      GdkEventKey *event);
 static gboolean gtk_file_chooser_entry_focus_out_event (GtkWidget       *widget,
                                                        GdkEventFocus   *event);
 
@@ -160,7 +152,6 @@ _gtk_file_chooser_entry_class_init (GtkFileChooserEntryClass *class)
   gobject_class->dispatch_properties_changed = gtk_file_chooser_entry_dispatch_properties_changed;
 
   widget_class->grab_focus = gtk_file_chooser_entry_grab_focus;
-  widget_class->key_press_event = gtk_file_chooser_entry_key_press_event;
   widget_class->focus_out_event = gtk_file_chooser_entry_focus_out_event;
 }
 
@@ -171,7 +162,6 @@ _gtk_file_chooser_entry_init (GtkFileChooserEntry *chooser_entry)
   GtkCellRenderer *cell;
 
   chooser_entry->local_only = TRUE;
-  chooser_entry->base_folder = g_file_new_for_path (g_get_home_dir ());
 
   g_object_set (chooser_entry, "truncate-multiline", TRUE, NULL);
 
@@ -200,6 +190,10 @@ _gtk_file_chooser_entry_init (GtkFileChooserEntry *chooser_entry)
 
   gtk_entry_set_completion (GTK_ENTRY (chooser_entry), comp);
   g_object_unref (comp);
+  /* NB: This needs to happen after the completion is set, so this handler
+   * runs before the handler installed by entrycompletion */
+  g_signal_connect (chooser_entry, "key-press-event",
+                    G_CALLBACK (gtk_file_chooser_entry_tab_handler), NULL);
 
 #ifdef G_OS_WIN32
   g_signal_connect (chooser_entry, "insert-text",
@@ -214,7 +208,8 @@ gtk_file_chooser_entry_finalize (GObject *object)
 {
   GtkFileChooserEntry *chooser_entry = GTK_FILE_CHOOSER_ENTRY (object);
 
-  g_object_unref (chooser_entry->base_folder);
+  if (chooser_entry->base_folder)
+    g_object_unref (chooser_entry->base_folder);
 
   if (chooser_entry->current_folder_file)
     g_object_unref (chooser_entry->current_folder_file);
@@ -238,23 +233,25 @@ gtk_file_chooser_entry_dispose (GObject *object)
 /* Match functions for the GtkEntryCompletion */
 static gboolean
 match_selected_callback (GtkEntryCompletion  *completion,
-                        GtkTreeModel        *model,
-                        GtkTreeIter         *iter,
-                        GtkFileChooserEntry *chooser_entry)
+                         GtkTreeModel        *model,
+                         GtkTreeIter         *iter,
+                         GtkFileChooserEntry *chooser_entry)
 {
   char *path;
-  
+  gint pos;
+
   gtk_tree_model_get (model, iter,
-                     FULL_PATH_COLUMN, &path,
+                      FULL_PATH_COLUMN, &path,
                       -1);
 
   gtk_editable_delete_text (GTK_EDITABLE (chooser_entry),
-                           0,
+                            0,
                             gtk_editable_get_position (GTK_EDITABLE (chooser_entry)));
+  pos = 0;
   gtk_editable_insert_text (GTK_EDITABLE (chooser_entry),
-                           path,
-                            0,
-                            NULL); 
+                            path,
+                            -1,
+                            &pos);
 
   g_free (path);
 
@@ -304,8 +301,10 @@ gtk_file_chooser_get_file_for_text (GtkFileChooserEntry *chooser_entry,
 
   if (str[0] == '~' || g_path_is_absolute (str) || has_uri_scheme (str))
     file = g_file_parse_name (str);
-  else
+  else if (chooser_entry->base_folder != NULL)
     file = g_file_resolve_relative_path (chooser_entry->base_folder, str);
+  else
+    file = NULL;
 
   return file;
 }
@@ -318,6 +317,9 @@ gtk_file_chooser_get_directory_for_text (GtkFileChooserEntry *chooser_entry,
 
   file = gtk_file_chooser_get_file_for_text (chooser_entry, text);
 
+  if (file == NULL)
+    return NULL;
+
   if (text[0] == 0 || text[strlen (text) - 1] == G_DIR_SEPARATOR)
     return file;
 
@@ -379,46 +381,37 @@ start_explicit_completion (GtkFileChooserEntry *chooser_entry)
 }
 
 static gboolean
-gtk_file_chooser_entry_key_press_event (GtkWidget *widget,
-                                       GdkEventKey *event)
+gtk_file_chooser_entry_tab_handler (GtkWidget *widget,
+                                   GdkEventKey *event)
 {
   GtkFileChooserEntry *chooser_entry;
   GtkEditable *editable;
   GdkModifierType state;
-  gboolean control_pressed;
+  gint start, end;
 
   chooser_entry = GTK_FILE_CHOOSER_ENTRY (widget);
   editable = GTK_EDITABLE (widget);
 
   if (!chooser_entry->eat_tabs)
-    return GTK_WIDGET_CLASS (_gtk_file_chooser_entry_parent_class)->key_press_event (widget, event);
+    return FALSE;
 
-  control_pressed = FALSE;
+  if (event->keyval != GDK_KEY_Tab)
+    return FALSE;
 
-  if (gtk_get_current_event_state (&state))
-    {
-      if ((state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
-       control_pressed = TRUE;
-    }
+  if (gtk_get_current_event_state (&state) &&
+      (state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
+    return FALSE;
 
   /* This is a bit evil -- it makes Tab never leave the entry. It basically
    * makes it 'safe' for people to hit. */
-  if (event->keyval == GDK_KEY_Tab && !control_pressed)
-    {
-      gint start, end;
-
-      gtk_editable_get_selection_bounds (editable, &start, &end);
+  gtk_editable_get_selection_bounds (editable, &start, &end);
       
-      if (start != end)
-        gtk_editable_set_position (editable, MAX (start, end));
-      else
-       start_explicit_completion (chooser_entry);
-
-      return TRUE;
-     }
-
-  return GTK_WIDGET_CLASS (_gtk_file_chooser_entry_parent_class)->key_press_event (widget, event);
+  if (start != end)
+    gtk_editable_set_position (editable, MAX (start, end));
+  else
+    start_explicit_completion (chooser_entry);
 
+  return TRUE;
 }
 
 static gboolean
@@ -432,6 +425,30 @@ gtk_file_chooser_entry_focus_out_event (GtkWidget     *widget,
   return GTK_WIDGET_CLASS (_gtk_file_chooser_entry_parent_class)->focus_out_event (widget, event);
 }
 
+static void
+update_inline_completion (GtkFileChooserEntry *chooser_entry)
+{
+  GtkEntryCompletion *completion = gtk_entry_get_completion (GTK_ENTRY (chooser_entry));
+
+  if (!chooser_entry->current_folder_loaded)
+    {
+      gtk_entry_completion_set_inline_completion (completion, FALSE);
+      return;
+    }
+
+  switch (chooser_entry->action)
+    {
+    case GTK_FILE_CHOOSER_ACTION_OPEN:
+    case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER:
+      gtk_entry_completion_set_inline_completion (completion, TRUE);
+      break;
+    case GTK_FILE_CHOOSER_ACTION_SAVE:
+    case GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER:
+      gtk_entry_completion_set_inline_completion (completion, FALSE);
+      break;
+    }
+}
+
 static void
 discard_completion_store (GtkFileChooserEntry *chooser_entry)
 {
@@ -439,7 +456,7 @@ discard_completion_store (GtkFileChooserEntry *chooser_entry)
     return;
 
   gtk_entry_completion_set_model (gtk_entry_get_completion (GTK_ENTRY (chooser_entry)), NULL);
-  gtk_entry_completion_set_inline_completion (gtk_entry_get_completion (GTK_ENTRY (chooser_entry)), FALSE);
+  update_inline_completion (chooser_entry);
   g_object_unref (chooser_entry->completion_store);
   chooser_entry->completion_store = NULL;
 }
@@ -530,7 +547,7 @@ finished_loading_cb (GtkFileSystemModel  *model,
   gtk_widget_set_tooltip_text (GTK_WIDGET (chooser_entry), NULL);
 
   completion = gtk_entry_get_completion (GTK_ENTRY (chooser_entry));
-  gtk_entry_completion_set_inline_completion (completion, TRUE);
+  update_inline_completion (chooser_entry);
   gtk_entry_completion_complete (completion);
   gtk_entry_completion_insert_prefix (completion);
 }
@@ -541,7 +558,7 @@ set_completion_folder (GtkFileChooserEntry *chooser_entry,
 {
   if (folder_file &&
       chooser_entry->local_only
-      && !g_file_is_native (folder_file))
+      && !_gtk_file_has_native_path (folder_file))
     folder_file = NULL;
 
   if ((chooser_entry->current_folder_file
@@ -713,16 +730,16 @@ void
 _gtk_file_chooser_entry_set_base_folder (GtkFileChooserEntry *chooser_entry,
                                         GFile               *file)
 {
+  g_return_if_fail (GTK_IS_FILE_CHOOSER_ENTRY (chooser_entry));
+  g_return_if_fail (file == NULL || G_IS_FILE (file));
+
+  if (chooser_entry->base_folder == file ||
+      (file != NULL && chooser_entry->base_folder != NULL 
+       && g_file_equal (chooser_entry->base_folder, file)))
+    return;
+
   if (file)
     g_object_ref (file);
-  else
-    file = g_file_new_for_path (g_get_home_dir ());
-
-  if (g_file_equal (chooser_entry->base_folder, file))
-    {
-      g_object_unref (file);
-      return;
-    }
 
   if (chooser_entry->base_folder)
     g_object_unref (chooser_entry->base_folder);
@@ -823,6 +840,8 @@ _gtk_file_chooser_entry_set_action (GtkFileChooserEntry *chooser_entry,
         _gtk_file_system_model_set_show_files (GTK_FILE_SYSTEM_MODEL (chooser_entry->completion_store),
                                                action == GTK_FILE_CHOOSER_ACTION_OPEN ||
                                                action == GTK_FILE_CHOOSER_ACTION_SAVE);
+
+      update_inline_completion (chooser_entry);
     }
 }