summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog39
-rw-r--r--ChangeLog.pre-2-1039
-rw-r--r--ChangeLog.pre-2-639
-rw-r--r--ChangeLog.pre-2-839
-rw-r--r--docs/reference/gtk/gtk-docs.sgml4
-rw-r--r--docs/reference/gtk/gtk-sections.txt5
-rw-r--r--docs/reference/gtk/gtk.types3
-rw-r--r--docs/reference/gtk/tmpl/gtkaboutdialog.sgml5
-rw-r--r--docs/reference/gtk/tmpl/gtkcellrenderercombo.sgml45
-rw-r--r--docs/reference/gtk/tmpl/gtkcellview.sgml16
-rw-r--r--docs/reference/gtk/tmpl/gtkfilechooserbutton.sgml28
-rw-r--r--docs/reference/gtk/tmpl/gtklabel.sgml23
-rw-r--r--gtk/.cvsignore1
-rw-r--r--gtk/gtkentrycompletion.c10
-rw-r--r--gtk/gtkfilechooserbutton.c1007
-rw-r--r--gtk/gtkfilechooserbutton.h4
-rw-r--r--gtk/gtklabel.c105
-rw-r--r--gtk/gtklabel.h3
-rw-r--r--tests/.cvsignore1
-rw-r--r--tests/testfilechooserbutton.c98
20 files changed, 1223 insertions, 291 deletions
diff --git a/ChangeLog b/ChangeLog
index bc0600b659..eba389232b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,42 @@
+2004-10-25 James M. Cape <jcape@ignore-your.tv>
+
+ Rework of GtkFileChooserButton, some cleanups. Fixes #154388,
+ #154390, #154390, #156272.
+
+ * docs/reference/gtk/gtk-docs.sgml: Moved GtkFileChooserButton
+ below GtkFileChooser.
+ * docs/reference/gtk/gtk-sections.txt: Added
+ gtk_file_chooser_button_get_width_chars(),
+ gtk_file_chooser_button_set_width_chars(),
+ gtk_label_set_width_chars(), gtk_label_get_width_chars().
+ * docs/reference/gtk/gtk.types: Added
+ gtk_cell_renderer_combo_get_type,
+ gtk_cell_view_get_type,
+ gtk_text_iter_get_type.
+ * docs/reference/gtk/tmpl/gtkaboutdialog.sgml: Add
+ "logo-icon-name" property.
+ * docs/reference/gtk/tmpl/gtkcellview.sgml: Updates for properties
+ (b/c of get_type() inclusion above).
+ * docs/reference/gtk/tmpl/gtkfilechooserbutton.sgml:
+ * docs/reference/gtk/tmpl/gtklabel.sgml: Add "width-chars" property,
+ getters/setters.
+ * docs/reference/gtk/tmpl/gtkcellrenderercombo.sgml: Added.
+ * gtk/gtkentrycompletion.c:
+ (_gtk_entry_completion_popdown): Don't show if the entry isn't
+ mapped.
+ * gtk/gtkfilechooserbutton.[c,h]: (*): About 45%
+ rewritten, adds "width-chars" property, icons, working save modes,
+ volume/Home/Desktop friendly-naming support.
+ * gtk/gtklabel.[c,h]:
+ (gtk_label_class_init), (gtk_label_init),
+ (gtk_label_get_property), (gtk_label_set_property),
+ (gtk_label_get_width_chars), (gtk_label_set_width_chars),
+ (gtk_label_size_request): Add "width-chars" property.
+ * tests/testfilechooserbutton.c: Update, use 4 different buttons for
+ the different ACTIONs.
+ * gtk/.cvsignore: Ignore gtk-update-icon-cache.
+ * tests/.cvsignore: Ignore testimage.
+
2004-10-25 Matthias Clasen <mclasen@redhat.com>
* gtk/gtkcellrenderercombo.c (find_text): Don't leak text. (#156325,
diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10
index bc0600b659..eba389232b 100644
--- a/ChangeLog.pre-2-10
+++ b/ChangeLog.pre-2-10
@@ -1,3 +1,42 @@
+2004-10-25 James M. Cape <jcape@ignore-your.tv>
+
+ Rework of GtkFileChooserButton, some cleanups. Fixes #154388,
+ #154390, #154390, #156272.
+
+ * docs/reference/gtk/gtk-docs.sgml: Moved GtkFileChooserButton
+ below GtkFileChooser.
+ * docs/reference/gtk/gtk-sections.txt: Added
+ gtk_file_chooser_button_get_width_chars(),
+ gtk_file_chooser_button_set_width_chars(),
+ gtk_label_set_width_chars(), gtk_label_get_width_chars().
+ * docs/reference/gtk/gtk.types: Added
+ gtk_cell_renderer_combo_get_type,
+ gtk_cell_view_get_type,
+ gtk_text_iter_get_type.
+ * docs/reference/gtk/tmpl/gtkaboutdialog.sgml: Add
+ "logo-icon-name" property.
+ * docs/reference/gtk/tmpl/gtkcellview.sgml: Updates for properties
+ (b/c of get_type() inclusion above).
+ * docs/reference/gtk/tmpl/gtkfilechooserbutton.sgml:
+ * docs/reference/gtk/tmpl/gtklabel.sgml: Add "width-chars" property,
+ getters/setters.
+ * docs/reference/gtk/tmpl/gtkcellrenderercombo.sgml: Added.
+ * gtk/gtkentrycompletion.c:
+ (_gtk_entry_completion_popdown): Don't show if the entry isn't
+ mapped.
+ * gtk/gtkfilechooserbutton.[c,h]: (*): About 45%
+ rewritten, adds "width-chars" property, icons, working save modes,
+ volume/Home/Desktop friendly-naming support.
+ * gtk/gtklabel.[c,h]:
+ (gtk_label_class_init), (gtk_label_init),
+ (gtk_label_get_property), (gtk_label_set_property),
+ (gtk_label_get_width_chars), (gtk_label_set_width_chars),
+ (gtk_label_size_request): Add "width-chars" property.
+ * tests/testfilechooserbutton.c: Update, use 4 different buttons for
+ the different ACTIONs.
+ * gtk/.cvsignore: Ignore gtk-update-icon-cache.
+ * tests/.cvsignore: Ignore testimage.
+
2004-10-25 Matthias Clasen <mclasen@redhat.com>
* gtk/gtkcellrenderercombo.c (find_text): Don't leak text. (#156325,
diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6
index bc0600b659..eba389232b 100644
--- a/ChangeLog.pre-2-6
+++ b/ChangeLog.pre-2-6
@@ -1,3 +1,42 @@
+2004-10-25 James M. Cape <jcape@ignore-your.tv>
+
+ Rework of GtkFileChooserButton, some cleanups. Fixes #154388,
+ #154390, #154390, #156272.
+
+ * docs/reference/gtk/gtk-docs.sgml: Moved GtkFileChooserButton
+ below GtkFileChooser.
+ * docs/reference/gtk/gtk-sections.txt: Added
+ gtk_file_chooser_button_get_width_chars(),
+ gtk_file_chooser_button_set_width_chars(),
+ gtk_label_set_width_chars(), gtk_label_get_width_chars().
+ * docs/reference/gtk/gtk.types: Added
+ gtk_cell_renderer_combo_get_type,
+ gtk_cell_view_get_type,
+ gtk_text_iter_get_type.
+ * docs/reference/gtk/tmpl/gtkaboutdialog.sgml: Add
+ "logo-icon-name" property.
+ * docs/reference/gtk/tmpl/gtkcellview.sgml: Updates for properties
+ (b/c of get_type() inclusion above).
+ * docs/reference/gtk/tmpl/gtkfilechooserbutton.sgml:
+ * docs/reference/gtk/tmpl/gtklabel.sgml: Add "width-chars" property,
+ getters/setters.
+ * docs/reference/gtk/tmpl/gtkcellrenderercombo.sgml: Added.
+ * gtk/gtkentrycompletion.c:
+ (_gtk_entry_completion_popdown): Don't show if the entry isn't
+ mapped.
+ * gtk/gtkfilechooserbutton.[c,h]: (*): About 45%
+ rewritten, adds "width-chars" property, icons, working save modes,
+ volume/Home/Desktop friendly-naming support.
+ * gtk/gtklabel.[c,h]:
+ (gtk_label_class_init), (gtk_label_init),
+ (gtk_label_get_property), (gtk_label_set_property),
+ (gtk_label_get_width_chars), (gtk_label_set_width_chars),
+ (gtk_label_size_request): Add "width-chars" property.
+ * tests/testfilechooserbutton.c: Update, use 4 different buttons for
+ the different ACTIONs.
+ * gtk/.cvsignore: Ignore gtk-update-icon-cache.
+ * tests/.cvsignore: Ignore testimage.
+
2004-10-25 Matthias Clasen <mclasen@redhat.com>
* gtk/gtkcellrenderercombo.c (find_text): Don't leak text. (#156325,
diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8
index bc0600b659..eba389232b 100644
--- a/ChangeLog.pre-2-8
+++ b/ChangeLog.pre-2-8
@@ -1,3 +1,42 @@
+2004-10-25 James M. Cape <jcape@ignore-your.tv>
+
+ Rework of GtkFileChooserButton, some cleanups. Fixes #154388,
+ #154390, #154390, #156272.
+
+ * docs/reference/gtk/gtk-docs.sgml: Moved GtkFileChooserButton
+ below GtkFileChooser.
+ * docs/reference/gtk/gtk-sections.txt: Added
+ gtk_file_chooser_button_get_width_chars(),
+ gtk_file_chooser_button_set_width_chars(),
+ gtk_label_set_width_chars(), gtk_label_get_width_chars().
+ * docs/reference/gtk/gtk.types: Added
+ gtk_cell_renderer_combo_get_type,
+ gtk_cell_view_get_type,
+ gtk_text_iter_get_type.
+ * docs/reference/gtk/tmpl/gtkaboutdialog.sgml: Add
+ "logo-icon-name" property.
+ * docs/reference/gtk/tmpl/gtkcellview.sgml: Updates for properties
+ (b/c of get_type() inclusion above).
+ * docs/reference/gtk/tmpl/gtkfilechooserbutton.sgml:
+ * docs/reference/gtk/tmpl/gtklabel.sgml: Add "width-chars" property,
+ getters/setters.
+ * docs/reference/gtk/tmpl/gtkcellrenderercombo.sgml: Added.
+ * gtk/gtkentrycompletion.c:
+ (_gtk_entry_completion_popdown): Don't show if the entry isn't
+ mapped.
+ * gtk/gtkfilechooserbutton.[c,h]: (*): About 45%
+ rewritten, adds "width-chars" property, icons, working save modes,
+ volume/Home/Desktop friendly-naming support.
+ * gtk/gtklabel.[c,h]:
+ (gtk_label_class_init), (gtk_label_init),
+ (gtk_label_get_property), (gtk_label_set_property),
+ (gtk_label_get_width_chars), (gtk_label_set_width_chars),
+ (gtk_label_size_request): Add "width-chars" property.
+ * tests/testfilechooserbutton.c: Update, use 4 different buttons for
+ the different ACTIONs.
+ * gtk/.cvsignore: Ignore gtk-update-icon-cache.
+ * tests/.cvsignore: Ignore testimage.
+
2004-10-25 Matthias Clasen <mclasen@redhat.com>
* gtk/gtkcellrenderercombo.c (find_text): Don't leak text. (#156325,
diff --git a/docs/reference/gtk/gtk-docs.sgml b/docs/reference/gtk/gtk-docs.sgml
index 462afea8a5..81cdb87c10 100644
--- a/docs/reference/gtk/gtk-docs.sgml
+++ b/docs/reference/gtk/gtk-docs.sgml
@@ -444,8 +444,8 @@ that is, GUI components such as <link linkend="GtkButton">GtkButton</link> or
&GtkColorSelection;
&GtkColorSelectionDialog;
&GtkFileSelection;
- &GtkFileChooserButton;
&GtkFileChooser;
+ &GtkFileChooserButton;
&GtkFileChooserDialog;
&GtkFileChooserWidget;
&GtkFileFilter;
@@ -599,5 +599,3 @@ that is, GUI components such as <link linkend="GtkButton">GtkButton</link> or
</index>
</book>
-
-
diff --git a/docs/reference/gtk/gtk-sections.txt b/docs/reference/gtk/gtk-sections.txt
index 26aed24935..c8d165dca8 100644
--- a/docs/reference/gtk/gtk-sections.txt
+++ b/docs/reference/gtk/gtk-sections.txt
@@ -1285,6 +1285,8 @@ gtk_file_chooser_button_get_title
gtk_file_chooser_button_set_title
gtk_file_chooser_button_get_active
gtk_file_chooser_button_set_active
+gtk_file_chooser_button_get_width_chars
+gtk_file_chooser_button_set_width_chars
<SUBSECTION Standard>
GTK_FILE_CHOOSER_BUTTON
GTK_IS_FILE_CHOOSER_BUTTON
@@ -1903,6 +1905,7 @@ gtk_label_set_markup_with_mnemonic
gtk_label_set_pattern
gtk_label_set_justify
gtk_label_set_ellipsize
+gtk_label_set_width_chars
gtk_label_get
gtk_label_parse_uline
gtk_label_set_line_wrap
@@ -1919,6 +1922,7 @@ gtk_label_set_text_with_mnemonic
gtk_label_get_attributes
gtk_label_get_justify
gtk_label_get_ellipsize
+gtk_label_get_width_chars
gtk_label_get_label
gtk_label_get_layout
gtk_label_get_line_wrap
@@ -5532,4 +5536,3 @@ gtk_icon_factory_get_type
gtk_icon_set_get_type
gtk_icon_source_get_type
</SECTION>
-
diff --git a/docs/reference/gtk/gtk.types b/docs/reference/gtk/gtk.types
index d983e18725..f0b2561ed1 100644
--- a/docs/reference/gtk/gtk.types
+++ b/docs/reference/gtk/gtk.types
@@ -18,10 +18,12 @@ gtk_button_get_type
gtk_calendar_get_type
gtk_cell_layout_get_type
gtk_cell_renderer_get_type
+gtk_cell_renderer_combo_get_type
gtk_cell_renderer_pixbuf_get_type
gtk_cell_renderer_text_get_type
gtk_cell_renderer_toggle_get_type
gtk_cell_renderer_progress_get_type
+gtk_cell_view_get_type
gtk_check_button_get_type
gtk_check_menu_item_get_type
gtk_clist_get_type
@@ -118,6 +120,7 @@ gtk_tearoff_menu_item_get_type
gtk_text_buffer_get_type
gtk_text_child_anchor_get_type
gtk_text_get_type
+gtk_text_iter_get_type
gtk_text_mark_get_type
gtk_text_tag_get_type
gtk_text_tag_table_get_type
diff --git a/docs/reference/gtk/tmpl/gtkaboutdialog.sgml b/docs/reference/gtk/tmpl/gtkaboutdialog.sgml
index 1f7dd84dc9..284e4491c4 100644
--- a/docs/reference/gtk/tmpl/gtkaboutdialog.sgml
+++ b/docs/reference/gtk/tmpl/gtkaboutdialog.sgml
@@ -67,6 +67,11 @@ only private fields and should not be directly accessed.
</para>
+<!-- ##### ARG GtkAboutDialog:logo-icon-name ##### -->
+<para>
+
+</para>
+
<!-- ##### ARG GtkAboutDialog:name ##### -->
<para>
diff --git a/docs/reference/gtk/tmpl/gtkcellrenderercombo.sgml b/docs/reference/gtk/tmpl/gtkcellrenderercombo.sgml
new file mode 100644
index 0000000000..e0353c1119
--- /dev/null
+++ b/docs/reference/gtk/tmpl/gtkcellrenderercombo.sgml
@@ -0,0 +1,45 @@
+<!-- ##### SECTION Title ##### -->
+GtkCellRendererCombo
+
+<!-- ##### SECTION Short_Description ##### -->
+
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### STRUCT GtkCellRendererCombo ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### ARG GtkCellRendererCombo:has-entry ##### -->
+<para>
+
+</para>
+
+<!-- ##### ARG GtkCellRendererCombo:model ##### -->
+<para>
+
+</para>
+
+<!-- ##### ARG GtkCellRendererCombo:text-column ##### -->
+<para>
+
+</para>
+
+<!-- ##### FUNCTION gtk_cell_renderer_combo_new ##### -->
+<para>
+
+</para>
+
+@Returns:
+
+
diff --git a/docs/reference/gtk/tmpl/gtkcellview.sgml b/docs/reference/gtk/tmpl/gtkcellview.sgml
index 24c388ca38..ec0072bce6 100644
--- a/docs/reference/gtk/tmpl/gtkcellview.sgml
+++ b/docs/reference/gtk/tmpl/gtkcellview.sgml
@@ -19,7 +19,21 @@ A widget displaying a single row of a GtkTreeModel
</para>
-@parent_instance:
+
+<!-- ##### ARG GtkCellView:background ##### -->
+<para>
+
+</para>
+
+<!-- ##### ARG GtkCellView:background-gdk ##### -->
+<para>
+
+</para>
+
+<!-- ##### ARG GtkCellView:background-set ##### -->
+<para>
+
+</para>
<!-- ##### FUNCTION gtk_cell_view_new ##### -->
<para>
diff --git a/docs/reference/gtk/tmpl/gtkfilechooserbutton.sgml b/docs/reference/gtk/tmpl/gtkfilechooserbutton.sgml
index 09c476c01c..3c03093237 100644
--- a/docs/reference/gtk/tmpl/gtkfilechooserbutton.sgml
+++ b/docs/reference/gtk/tmpl/gtkfilechooserbutton.sgml
@@ -57,8 +57,9 @@ look like a #GtkButton.
<important>
<para>
The #GtkFileChooserButton will ellipsize the label while in Open mode,
-and thus will thus request little horizontal space. To give the dialog
-more space, you should call gtk_widget_size_request(), or pack it in
+and thus will thus request little horizontal space. To give the button
+more space, you should call gtk_widget_size_request(),
+gtk_file_chooser_button_set_width_chars (), or pack the button in
such a way that other interface elements give space to the widget.
</para>
</important>
@@ -91,6 +92,11 @@ Instance of the #GtkFileChooserDialog associated with the button.
Title to put on the #GtkFileChooserDialog associated with the button.
</para>
+<!-- ##### ARG GtkFileChooserButton:width-chars ##### -->
+<para>
+The width of the entry and label inside the button, in characters.
+</para>
+
<!-- ##### FUNCTION gtk_file_chooser_button_new ##### -->
<para>
@@ -155,3 +161,21 @@ Title to put on the #GtkFileChooserDialog associated with the button.
@is_active:
+<!-- ##### FUNCTION gtk_file_chooser_button_get_width_chars ##### -->
+<para>
+
+</para>
+
+@button:
+@Returns:
+
+
+<!-- ##### FUNCTION gtk_file_chooser_button_set_width_chars ##### -->
+<para>
+
+</para>
+
+@button:
+@n_chars:
+
+
diff --git a/docs/reference/gtk/tmpl/gtklabel.sgml b/docs/reference/gtk/tmpl/gtklabel.sgml
index a58a43fbe2..4d9c108f84 100644
--- a/docs/reference/gtk/tmpl/gtklabel.sgml
+++ b/docs/reference/gtk/tmpl/gtklabel.sgml
@@ -230,6 +230,11 @@ described below.
</para>
+<!-- ##### ARG GtkLabel:width-chars ##### -->
+<para>
+
+</para>
+
<!-- ##### ARG GtkLabel:wrap ##### -->
<para>
@@ -310,6 +315,15 @@ The pattern of underlines you want under the existing text within the
@mode:
+<!-- ##### FUNCTION gtk_label_set_width_chars ##### -->
+<para>
+
+</para>
+
+@label:
+@n_chars:
+
+
<!-- ##### FUNCTION gtk_label_get ##### -->
<para>
Gets the current string of text within the #GtkLabel and writes it to
@@ -462,6 +476,15 @@ Gtk+ 1.0.x.
@Returns:
+<!-- ##### FUNCTION gtk_label_get_width_chars ##### -->
+<para>
+
+</para>
+
+@label:
+@Returns:
+
+
<!-- ##### FUNCTION gtk_label_get_label ##### -->
<para>
diff --git a/gtk/.cvsignore b/gtk/.cvsignore
index 2407e9490d..0eb579021e 100644
--- a/gtk/.cvsignore
+++ b/gtk/.cvsignore
@@ -24,3 +24,4 @@ stamp-gtkmarshalers.h
gtk-query-immodules-2.0
.saved
gtkalias.h
+gtk-update-icon-cache
diff --git a/gtk/gtkentrycompletion.c b/gtk/gtkentrycompletion.c
index 089fb76534..689debb8f9 100644
--- a/gtk/gtkentrycompletion.c
+++ b/gtk/gtkentrycompletion.c
@@ -1258,7 +1258,10 @@ _gtk_entry_completion_resize_popup (GtkEntryCompletion *completion)
GtkTreePath *path;
gboolean above;
gint width;
-
+
+ if (!completion->priv->entry->window)
+ return FALSE;
+
gdk_window_get_origin (completion->priv->entry->window, &x, &y);
_gtk_entry_get_borders (GTK_ENTRY (completion->priv->entry), &x_border, &y_border);
@@ -1343,6 +1346,9 @@ _gtk_entry_completion_popup (GtkEntryCompletion *completion)
if (GTK_WIDGET_MAPPED (completion->priv->popup_window))
return;
+ if (!GTK_WIDGET_MAPPED (completion->priv->entry))
+ return;
+
completion->priv->ignore_enter = TRUE;
column = gtk_tree_view_get_column (GTK_TREE_VIEW (completion->priv->action_view), 0);
@@ -1358,7 +1364,7 @@ _gtk_entry_completion_popup (GtkEntryCompletion *completion)
_gtk_entry_completion_resize_popup (completion);
gtk_widget_show (completion->priv->popup_window);
-
+
gtk_grab_add (completion->priv->popup_window);
gdk_pointer_grab (completion->priv->popup_window->window, TRUE,
GDK_BUTTON_PRESS_MASK |
diff --git a/gtk/gtkfilechooserbutton.c b/gtk/gtkfilechooserbutton.c
index 5ebdac05b5..3c262df93b 100644
--- a/gtk/gtkfilechooserbutton.c
+++ b/gtk/gtkfilechooserbutton.c
@@ -56,7 +56,12 @@
#define GTK_FILE_CHOOSER_BUTTON_GET_PRIVATE(object) (GTK_FILE_CHOOSER_BUTTON ((object))->priv)
#define DEFAULT_FILENAME N_("(None)")
-#define DEFAULT_SPACING 0
+#define MIN_LABEL_WIDTH 100
+#define ENTRY_BUTTON_SPACING 0
+#define FALLBACK_ICON_SIZE 20
+#define FALLBACK_ICON_NAME "stock_unknown"
+#define NEW_FILE_ICON_NAME "stock_new"
+#define NEW_DIR_ICON_NAME "stock_new-dir"
/* ********************** *
* Private Enumerations *
@@ -69,7 +74,8 @@ enum
PROP_DIALOG,
PROP_TITLE,
- PROP_ACTIVE
+ PROP_ACTIVE,
+ PROP_WIDTH_CHARS
};
@@ -80,17 +86,24 @@ enum
struct _GtkFileChooserButtonPrivate
{
GtkWidget *dialog;
+ GtkWidget *accept_button;
+ GtkWidget *entry_box;
+ GtkWidget *entry_image;
GtkWidget *entry;
+ GtkWidget *label_box;
+ GtkWidget *label_image;
GtkWidget *label;
- GtkWidget *separator;
GtkWidget *button;
- gchar *filesystem;
+ gchar *backend;
gulong entry_changed_id;
gulong dialog_file_activated_id;
gulong dialog_folder_changed_id;
gulong dialog_selection_changed_id;
+ gulong dialog_selection_changed_proxy_id;
+ gulong settings_signal_id;
guint update_id;
+ gint icon_size;
};
@@ -109,12 +122,15 @@ enum
* ********************* */
/* GObject Functions */
+static GObject *gtk_file_chooser_button_constructor (GType type,
+ guint n_params,
+ GObjectConstructParam *params);
static void gtk_file_chooser_button_set_property (GObject *object,
- guint id,
+ guint param_id,
const GValue *value,
GParamSpec *pspec);
static void gtk_file_chooser_button_get_property (GObject *object,
- guint id,
+ guint param_id,
GValue *value,
GParamSpec *pspec);
@@ -131,14 +147,22 @@ static void gtk_file_chooser_button_drag_data_received (GtkWidget *wi
guint drag_time);
static void gtk_file_chooser_button_show_all (GtkWidget *widget);
static void gtk_file_chooser_button_hide_all (GtkWidget *widget);
+static void gtk_file_chooser_button_show (GtkWidget *widget);
+static void gtk_file_chooser_button_hide (GtkWidget *widget);
static gboolean gtk_file_chooser_button_mnemonic_activate (GtkWidget *widget,
gboolean group_cycling);
+static void gtk_file_chooser_button_style_set (GtkWidget *widget,
+ GtkStyle *old_style);
+static void gtk_file_chooser_button_screen_changed (GtkWidget *widget,
+ GdkScreen *old_screen);
/* Child Widget Callbacks */
static void dialog_update_preview_cb (GtkFileChooser *dialog,
gpointer user_data);
static void dialog_selection_changed_cb (GtkFileChooser *dialog,
gpointer user_data);
+static void dialog_selection_changed_proxy_cb (GtkFileChooser *dialog,
+ gpointer user_data);
static void dialog_file_activated_cb (GtkFileChooser *dialog,
gpointer user_data);
static void dialog_current_folder_changed_cb (GtkFileChooser *dialog,
@@ -162,16 +186,17 @@ static void button_notify_active_cb (GObject *re
static void entry_size_allocate_cb (GtkWidget *entry,
GtkAllocation *allocation,
gpointer user_data);
-static void entry_changed_cb (GtkEditable *chooser_entry,
+static void entry_changed_cb (GtkEditable *editable,
gpointer user_data);
/* Utility Functions */
-static void gtk_file_chooser_button_set_dialog (GObject *object,
- GtkWidget *dialog);
+static void remove_settings_signal (GtkFileChooserButton *button,
+ GdkScreen *screen);
-static gboolean update_dialog (gpointer user_data);
-static gboolean update_dialog_idle (gpointer user_data);
+static void update_dialog (GtkFileChooserButton *button);
static void update_entry (GtkFileChooserButton *button);
+static void update_label (GtkFileChooserButton *button);
+static void update_icons (GtkFileChooserButton *button);
/* ******************* *
@@ -198,6 +223,7 @@ gtk_file_chooser_button_class_init (GtkFileChooserButtonClass * class)
gtkobject_class = GTK_OBJECT_CLASS (class);
widget_class = GTK_WIDGET_CLASS (class);
+ gobject_class->constructor = gtk_file_chooser_button_constructor;
gobject_class->set_property = gtk_file_chooser_button_set_property;
gobject_class->get_property = gtk_file_chooser_button_get_property;
@@ -206,6 +232,10 @@ gtk_file_chooser_button_class_init (GtkFileChooserButtonClass * class)
widget_class->drag_data_received = gtk_file_chooser_button_drag_data_received;
widget_class->show_all = gtk_file_chooser_button_show_all;
widget_class->hide_all = gtk_file_chooser_button_hide_all;
+ widget_class->show = gtk_file_chooser_button_show;
+ widget_class->hide = gtk_file_chooser_button_hide;
+ widget_class->style_set = gtk_file_chooser_button_style_set;
+ widget_class->screen_changed = gtk_file_chooser_button_screen_changed;
widget_class->mnemonic_activate = gtk_file_chooser_button_mnemonic_activate;
g_object_class_install_property (gobject_class, PROP_DIALOG,
@@ -226,6 +256,12 @@ gtk_file_chooser_button_class_init (GtkFileChooserButtonClass * class)
P_("Active"),
P_("Whether the browse dialog is visible or not."),
FALSE, G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class, PROP_WIDTH_CHARS,
+ g_param_spec_int ("width-chars",
+ P_("Width In Characters"),
+ P_("The desired width of the button widget, in characters."),
+ -1, G_MAXINT, -1,
+ G_PARAM_READWRITE));
_gtk_file_chooser_install_properties (gobject_class);
@@ -237,18 +273,29 @@ static void
gtk_file_chooser_button_init (GtkFileChooserButton *button)
{
GtkFileChooserButtonPrivate *priv;
- GtkWidget *box, *image;
+ GtkWidget *box, *image, *sep;
- gtk_box_set_spacing (GTK_BOX (button), DEFAULT_SPACING);
+ gtk_box_set_spacing (GTK_BOX (button), ENTRY_BUTTON_SPACING);
priv = G_TYPE_INSTANCE_GET_PRIVATE (button, GTK_TYPE_FILE_CHOOSER_BUTTON,
GtkFileChooserButtonPrivate);
button->priv = priv;
+ priv->icon_size = FALLBACK_ICON_SIZE;
+
gtk_widget_push_composite_child ();
+ priv->entry_box = gtk_hbox_new (FALSE, 4);
+ gtk_container_add (GTK_CONTAINER (button), priv->entry_box);
+
+ priv->entry_image = gtk_image_new ();
+ gtk_box_pack_start (GTK_BOX (priv->entry_box), priv->entry_image,
+ FALSE, FALSE, 0);
+ gtk_widget_show (priv->entry_image);
+
priv->entry = _gtk_file_chooser_entry_new (FALSE);
- gtk_container_add (GTK_CONTAINER (button), priv->entry);
+ gtk_container_add (GTK_CONTAINER (priv->entry_box), priv->entry);
+ gtk_widget_show (priv->entry);
priv->button = gtk_toggle_button_new ();
g_signal_connect (priv->button, "toggled",
@@ -263,22 +310,31 @@ gtk_file_chooser_button_init (GtkFileChooserButton *button)
box = gtk_hbox_new (FALSE, 4);
gtk_container_add (GTK_CONTAINER (priv->button), box);
gtk_widget_show (box);
+
+ priv->label_box = gtk_hbox_new (FALSE, 6);
+ gtk_container_add (GTK_CONTAINER (box), priv->label_box);
+ gtk_widget_show (priv->label_box);
+
+ priv->label_image = gtk_image_new ();
+ gtk_box_pack_start (GTK_BOX (priv->label_box), priv->label_image,
+ FALSE, FALSE, 0);
+ gtk_widget_show (priv->label_image);
priv->label = gtk_label_new (_(DEFAULT_FILENAME));
gtk_label_set_ellipsize (GTK_LABEL (priv->label), PANGO_ELLIPSIZE_START);
gtk_misc_set_alignment (GTK_MISC (priv->label), 0.0, 0.5);
- gtk_box_pack_start (GTK_BOX (box), priv->label, TRUE, TRUE, 2);
+ gtk_container_add (GTK_CONTAINER (priv->label_box), priv->label);
gtk_widget_show (priv->label);
+ sep = gtk_vseparator_new ();
+ gtk_box_pack_end (GTK_BOX (priv->label_box), sep, FALSE, FALSE, 0);
+ gtk_widget_show (sep);
+
image = gtk_image_new_from_stock (GTK_STOCK_OPEN,
GTK_ICON_SIZE_SMALL_TOOLBAR);
gtk_box_pack_end (GTK_BOX (box), image, FALSE, FALSE, 0);
gtk_widget_show (image);
- priv->separator = gtk_vseparator_new ();
- gtk_box_pack_end (GTK_BOX (box), priv->separator, FALSE, FALSE, 0);
- gtk_widget_show (priv->separator);
-
gtk_widget_pop_composite_child ();
/* DnD */
@@ -297,10 +353,92 @@ gtk_file_chooser_button_init (GtkFileChooserButton *button)
* GObject Functions *
* ******************* */
+static GObject *
+gtk_file_chooser_button_constructor (GType type,
+ guint n_params,
+ GObjectConstructParam *params)
+{
+ GObject *object;
+ GtkFileChooserButtonPrivate *priv;
+ GtkFilePath *path;
+
+ object = (*G_OBJECT_CLASS (gtk_file_chooser_button_parent_class)->constructor) (type,
+ n_params,
+ params);
+ priv = GTK_FILE_CHOOSER_BUTTON_GET_PRIVATE (object);
+
+ if (!priv->dialog)
+ {
+ if (priv->backend)
+ priv->dialog = gtk_file_chooser_dialog_new_with_backend (NULL, NULL,
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ priv->backend, NULL);
+ else
+ priv->dialog = gtk_file_chooser_dialog_new (NULL, NULL,
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ NULL);
+
+ gtk_dialog_add_button (GTK_DIALOG (priv->dialog),
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+ priv->accept_button = gtk_dialog_add_button (GTK_DIALOG (priv->dialog),
+ GTK_STOCK_OPEN,
+ GTK_RESPONSE_ACCEPT);
+ gtk_dialog_set_default_response (GTK_DIALOG (priv->dialog),
+ GTK_RESPONSE_ACCEPT);
+
+ gtk_dialog_set_alternative_button_order (GTK_DIALOG (priv->dialog),
+ GTK_RESPONSE_ACCEPT,
+ GTK_RESPONSE_CANCEL,
+ -1);
+ }
+
+ g_free (priv->backend);
+ priv->backend = NULL;
+
+ g_signal_connect (priv->dialog, "delete-event",
+ G_CALLBACK (dialog_delete_event_cb), object);
+ g_signal_connect (priv->dialog, "response",
+ G_CALLBACK (dialog_response_cb), object);
+
+ /* This is used, instead of the standard delegate, to ensure that signals are only
+ * delegated when the OK button is pressed. */
+ g_object_set_qdata (object, GTK_FILE_CHOOSER_DELEGATE_QUARK, priv->dialog);
+ priv->dialog_folder_changed_id =
+ g_signal_connect (priv->dialog, "current-folder-changed",
+ G_CALLBACK (dialog_current_folder_changed_cb), object);
+ priv->dialog_file_activated_id =
+ g_signal_connect (priv->dialog, "file-activated",
+ G_CALLBACK (dialog_file_activated_cb), object);
+ priv->dialog_selection_changed_id =
+ g_signal_connect (priv->dialog, "selection-changed",
+ G_CALLBACK (dialog_selection_changed_cb), object);
+ priv->dialog_selection_changed_proxy_id =
+ g_signal_connect (priv->dialog, "selection-changed",
+ G_CALLBACK (dialog_selection_changed_proxy_cb), object);
+ g_signal_connect (priv->dialog, "update-preview",
+ G_CALLBACK (dialog_update_preview_cb), object);
+ g_signal_connect (priv->dialog, "notify",
+ G_CALLBACK (dialog_notify_cb), object);
+ g_object_add_weak_pointer (G_OBJECT (priv->dialog),
+ (gpointer *) (&priv->dialog));
+
+ _gtk_file_chooser_entry_set_file_system (GTK_FILE_CHOOSER_ENTRY (priv->entry),
+ _gtk_file_chooser_get_file_system (GTK_FILE_CHOOSER (priv->dialog)));
+ path = gtk_file_path_new_steal ("/");
+ _gtk_file_chooser_entry_set_base_folder (GTK_FILE_CHOOSER_ENTRY (priv->entry),
+ path);
+ priv->entry_changed_id = g_signal_connect (priv->entry, "changed",
+ G_CALLBACK (entry_changed_cb),
+ object);
+
+ update_label (GTK_FILE_CHOOSER_BUTTON (object));
+
+ return object;
+}
static void
gtk_file_chooser_button_set_property (GObject *object,
- guint id,
+ guint param_id,
const GValue *value,
GParamSpec *pspec)
{
@@ -308,39 +446,26 @@ gtk_file_chooser_button_set_property (GObject *object,
priv = GTK_FILE_CHOOSER_BUTTON_GET_PRIVATE (object);
- switch (id)
+ switch (param_id)
{
case PROP_DIALOG:
- {
- GtkWidget *widget;
-
- widget = g_value_get_object (value);
-
- if (widget == NULL)
- {
- widget = g_object_new (GTK_TYPE_FILE_CHOOSER_DIALOG,
- "file-system-backend", priv->filesystem, NULL);
- g_free (priv->filesystem);
- priv->filesystem = NULL;
-
- gtk_dialog_add_button (GTK_DIALOG (widget),
- GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
- gtk_dialog_add_button (GTK_DIALOG (widget),
- GTK_STOCK_OK, GTK_RESPONSE_ACCEPT);
- }
-
- gtk_file_chooser_button_set_dialog (object, widget);
- }
+ /* Construct-only */
+ priv->dialog = g_value_get_object (value);
break;
case PROP_ACTIVE:
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->button),
g_value_get_boolean (value));
break;
+ case PROP_WIDTH_CHARS:
+ gtk_file_chooser_button_set_width_chars (GTK_FILE_CHOOSER_BUTTON (object),
+ g_value_get_int (value));
+ break;
case GTK_FILE_CHOOSER_PROP_ACTION:
g_object_set_property (G_OBJECT (priv->dialog), pspec->name, value);
- _gtk_file_chooser_entry_set_action (priv->entry,
- (GtkFileChooserAction)g_value_get_enum (value));
+ _gtk_file_chooser_entry_set_action (GTK_FILE_CHOOSER_ENTRY (priv->entry),
+ (GtkFileChooserAction) g_value_get_enum (value));
+ update_icons (GTK_FILE_CHOOSER_BUTTON (object));
switch (g_value_get_enum (value))
{
@@ -348,22 +473,24 @@ gtk_file_chooser_button_set_property (GObject *object,
gtk_file_chooser_unselect_all (GTK_FILE_CHOOSER (priv->dialog));
/* Fall through to set the widget states */
case GTK_FILE_CHOOSER_ACTION_OPEN:
- gtk_widget_hide (priv->entry);
- gtk_widget_show (priv->label);
- gtk_widget_show (priv->separator);
+ gtk_widget_hide (priv->entry_box);
+ gtk_widget_show (priv->label_box);
gtk_box_set_child_packing (GTK_BOX (object), priv->button,
TRUE, TRUE, 0, GTK_PACK_START);
+ gtk_button_set_label (GTK_BUTTON (priv->accept_button),
+ GTK_STOCK_OPEN);
break;
case GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER:
gtk_file_chooser_unselect_all (GTK_FILE_CHOOSER (priv->dialog));
/* Fall through to set the widget states */
case GTK_FILE_CHOOSER_ACTION_SAVE:
- gtk_widget_show (priv->entry);
- gtk_widget_hide (priv->label);
- gtk_widget_hide (priv->separator);
+ gtk_widget_show (priv->entry_box);
+ gtk_widget_hide (priv->label_box);
gtk_box_set_child_packing (GTK_BOX (object), priv->button,
FALSE, FALSE, 0, GTK_PACK_START);
+ gtk_button_set_label (GTK_BUTTON (priv->accept_button),
+ GTK_STOCK_SAVE);
break;
}
break;
@@ -381,7 +508,7 @@ gtk_file_chooser_button_set_property (GObject *object,
case GTK_FILE_CHOOSER_PROP_FILE_SYSTEM_BACKEND:
/* Construct-only */
- priv->filesystem = g_value_dup_string (value);
+ priv->backend = g_value_dup_string (value);
break;
case GTK_FILE_CHOOSER_PROP_SELECT_MULTIPLE:
@@ -389,24 +516,30 @@ gtk_file_chooser_button_set_property (GObject *object,
G_STRFUNC, G_OBJECT_TYPE_NAME (object));
break;
default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, id, pspec);
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
break;
}
}
-
static void
gtk_file_chooser_button_get_property (GObject *object,
- guint id,
+ guint param_id,
GValue *value,
GParamSpec *pspec)
{
- GtkFileChooserButtonPrivate *priv = GTK_FILE_CHOOSER_BUTTON_GET_PRIVATE (object);
+ GtkFileChooserButtonPrivate *priv;
- switch (id)
+ priv = GTK_FILE_CHOOSER_BUTTON_GET_PRIVATE (object);
+
+ switch (param_id)
{
case PROP_ACTIVE:
- g_value_set_boolean (value, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->button)));
+ g_value_set_boolean (value,
+ gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->button)));
+ break;
+ case PROP_WIDTH_CHARS:
+ g_value_set_int (value,
+ gtk_entry_get_width_chars (GTK_ENTRY (priv->entry)));
break;
case PROP_TITLE:
@@ -424,7 +557,7 @@ gtk_file_chooser_button_get_property (GObject *object,
break;
default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, id, pspec);
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
break;
}
}
@@ -441,11 +574,14 @@ gtk_file_chooser_button_destroy (GtkObject * object)
priv = GTK_FILE_CHOOSER_BUTTON_GET_PRIVATE (object);
+ if (priv->update_id)
+ g_source_remove (priv->update_id);
+
if (priv->dialog != NULL)
gtk_widget_destroy (priv->dialog);
- if (priv->update_id != 0)
- g_source_remove (priv->update_id);
+ remove_settings_signal (GTK_FILE_CHOOSER_BUTTON (object),
+ gtk_widget_get_screen (GTK_WIDGET (object)));
if (GTK_OBJECT_CLASS (gtk_file_chooser_button_parent_class)->destroy != NULL)
(*GTK_OBJECT_CLASS (gtk_file_chooser_button_parent_class)->destroy) (object);
@@ -494,7 +630,6 @@ gtk_file_chooser_button_drag_data_received (GtkWidget *widget,
break;
selected = FALSE;
- g_signal_handler_block (priv->entry, priv->entry_changed_id);
for (i = 0; !selected && uris[i] != NULL; i++)
{
GtkFileSystem *fs;
@@ -542,7 +677,6 @@ gtk_file_chooser_button_drag_data_received (GtkWidget *widget,
gtk_file_path_free (path);
}
- g_signal_handler_unblock (priv->entry, priv->entry_changed_id);
g_strfreev (uris);
}
@@ -558,44 +692,151 @@ gtk_file_chooser_button_drag_data_received (GtkWidget *widget,
gtk_drag_finish (context, TRUE, FALSE, drag_time);
}
-
static void
gtk_file_chooser_button_show_all (GtkWidget *widget)
{
gtk_widget_show (widget);
}
-
static void
gtk_file_chooser_button_hide_all (GtkWidget *widget)
{
gtk_widget_hide (widget);
}
+static void
+gtk_file_chooser_button_show (GtkWidget *widget)
+{
+ GtkFileChooserButtonPrivate *priv;
+
+ priv = GTK_FILE_CHOOSER_BUTTON_GET_PRIVATE (widget);
+
+ if (GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->show)
+ (*GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->show) (widget);
+
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->button)))
+ gtk_widget_show (priv->dialog);
+}
+
+static void
+gtk_file_chooser_button_hide (GtkWidget *widget)
+{
+ GtkFileChooserButtonPrivate *priv;
+
+ priv = GTK_FILE_CHOOSER_BUTTON_GET_PRIVATE (widget);
+
+ gtk_widget_hide (priv->dialog);
+
+ if (GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->hide)
+ (*GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->hide) (widget);
+}
static gboolean
gtk_file_chooser_button_mnemonic_activate (GtkWidget *widget,
gboolean group_cycling)
{
- GtkFileChooserButton *button;
+ GtkFileChooserButtonPrivate *priv;
- button = GTK_FILE_CHOOSER_BUTTON (widget);
+ priv = GTK_FILE_CHOOSER_BUTTON_GET_PRIVATE (widget);
- switch (gtk_file_chooser_get_action (GTK_FILE_CHOOSER (button->priv->dialog)))
+ switch (gtk_file_chooser_get_action (GTK_FILE_CHOOSER (priv->dialog)))
{
case GTK_FILE_CHOOSER_ACTION_OPEN:
case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER:
- gtk_widget_grab_focus (button->priv->button);
+ gtk_widget_grab_focus (priv->button);
break;
case GTK_FILE_CHOOSER_ACTION_SAVE:
case GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER:
- gtk_widget_grab_focus (button->priv->entry);
+ gtk_widget_grab_focus (priv->entry);
break;
}
return TRUE;
}
+/* Changes the icons wherever it is needed */
+static void
+change_icon_theme (GtkFileChooserButton *button)
+{
+ GtkSettings *settings;
+ gint width, height;
+
+ settings = gtk_settings_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (button)));
+
+ if (gtk_icon_size_lookup_for_settings (settings, GTK_ICON_SIZE_SMALL_TOOLBAR,
+ &width, &height))
+ button->priv->icon_size = MAX (width, height);
+ else
+ button->priv->icon_size = FALLBACK_ICON_SIZE;
+
+ update_icons (button);
+}
+
+/* Callback used when a GtkSettings value changes */
+static void
+settings_notify_cb (GObject *object,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ const char *name;
+
+ name = g_param_spec_get_name (pspec);
+
+ if (strcmp (name, "gtk-icon-theme-name") == 0
+ || strcmp (name, "gtk-icon-sizes") == 0)
+ change_icon_theme (user_data);
+}
+
+/* Installs a signal handler for GtkSettings so that we can monitor changes in
+ * the icon theme.
+ */
+static void
+check_icon_theme (GtkFileChooserButton *button)
+{
+ GtkSettings *settings;
+
+ if (button->priv->settings_signal_id)
+ return;
+
+ if (gtk_widget_has_screen (GTK_WIDGET (button)))
+ {
+ settings = gtk_settings_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (button)));
+ button->priv->settings_signal_id = g_signal_connect (settings, "notify",
+ G_CALLBACK (settings_notify_cb),
+ button);
+
+ change_icon_theme (button);
+ }
+}
+
+static void
+gtk_file_chooser_button_style_set (GtkWidget *widget,
+ GtkStyle *old_style)
+{
+ if (GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->style_set)
+ (*GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->style_set) (widget,
+ old_style);
+
+ if (gtk_widget_has_screen (widget))
+ change_icon_theme (GTK_FILE_CHOOSER_BUTTON (widget));
+}
+
+static void
+gtk_file_chooser_button_screen_changed (GtkWidget *widget,
+ GdkScreen *old_screen)
+{
+ GtkFileChooserButton *button;
+
+ button = GTK_FILE_CHOOSER_BUTTON (widget);
+
+ if (GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->screen_changed)
+ (*GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->screen_changed) (widget,
+ old_screen);
+
+ remove_settings_signal (button, old_screen);
+ check_icon_theme (button);
+}
+
/* ************************************************************************** *
* Public API *
@@ -614,7 +855,9 @@ gtk_file_chooser_button_mnemonic_activate (GtkWidget *widget,
GtkWidget *
gtk_file_chooser_button_new (const gchar *title)
{
- return g_object_new (GTK_TYPE_FILE_CHOOSER_BUTTON, "title", title, NULL);
+ return g_object_new (GTK_TYPE_FILE_CHOOSER_BUTTON,
+ "title", title,
+ NULL);
}
/**
@@ -632,11 +875,12 @@ GtkWidget *
gtk_file_chooser_button_new_with_backend (const gchar *title,
const gchar *backend)
{
- return g_object_new (GTK_TYPE_FILE_CHOOSER_BUTTON, "title", title,
- "file-system-backend", backend, NULL);
+ return g_object_new (GTK_TYPE_FILE_CHOOSER_BUTTON,
+ "title", title,
+ "file-system-backend", backend,
+ NULL);
}
-
/**
* gtk_file_chooser_button_new_with_dialog:
* @dialog: the #GtkDialog widget to use.
@@ -654,10 +898,11 @@ gtk_file_chooser_button_new_with_dialog (GtkWidget *dialog)
{
g_return_val_if_fail (GTK_IS_FILE_CHOOSER_DIALOG (dialog), NULL);
- return g_object_new (GTK_TYPE_FILE_CHOOSER_BUTTON, "dialog", dialog, NULL);
+ return g_object_new (GTK_TYPE_FILE_CHOOSER_BUTTON,
+ "dialog", dialog,
+ NULL);
}
-
/**
* gtk_file_chooser_button_set_title:
* @button: the button widget to modify.
@@ -677,7 +922,6 @@ gtk_file_chooser_button_set_title (GtkFileChooserButton *button,
g_object_notify (G_OBJECT (button), "title");
}
-
/**
* gtk_file_chooser_button_get_title:
* @button: the button widget to examine.
@@ -697,7 +941,6 @@ gtk_file_chooser_button_get_title (GtkFileChooserButton *button)
return gtk_window_get_title (GTK_WINDOW (button->priv->dialog));
}
-
/**
* gtk_file_chooser_button_set_active:
* @button: the button widget to modify.
@@ -716,7 +959,6 @@ gtk_file_chooser_button_set_active (GtkFileChooserButton *button,
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button->priv->button), is_active);
}
-
/**
* gtk_file_chooser_button_get_active:
* @button: the button widget to examine.
@@ -735,193 +977,411 @@ gtk_file_chooser_button_get_active (GtkFileChooserButton *button)
return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button->priv->button));
}
+/**
+ * gtk_file_chooser_button_get_width_chars:
+ * @button: the button widget to examine.
+ *
+ * Retrieves the width in characters of the @button widget's entry and/or label.
+ *
+ * Returns: an integer width (in characters) that the button will use to size itself.
+ *
+ * Since: 2.6
+ **/
+gint
+gtk_file_chooser_button_get_width_chars (GtkFileChooserButton *button)
+{
+ g_return_val_if_fail (GTK_IS_FILE_CHOOSER_BUTTON (button), -1);
+
+ return gtk_entry_get_width_chars (GTK_ENTRY (button->priv->entry));
+}
+
+/**
+ * gtk_file_chooser_button_set_width_chars:
+ * @button: the button widget to examine.
+ * @n_chars: the new width, in chracters.
+ *
+ * Sets the width (in characters) that @button will use to @n_chars.
+ *
+ * Since: 2.6
+ **/
+void
+gtk_file_chooser_button_set_width_chars (GtkFileChooserButton *button,
+ gint n_chars)
+{
+ g_return_if_fail (GTK_IS_FILE_CHOOSER_BUTTON (button));
+
+ gtk_entry_set_width_chars (GTK_ENTRY (button->priv->entry), n_chars);
+ gtk_label_set_width_chars (GTK_LABEL (button->priv->label), n_chars);
+ g_object_notify (G_OBJECT (button), "width-chars");
+}
+
/* ******************* *
* Utility Functions *
* ******************* */
+/* Removes the settings signal handler. It's safe to call multiple times */
static void
-gtk_file_chooser_button_set_dialog (GObject *object,
- GtkWidget *dialog)
+remove_settings_signal (GtkFileChooserButton *button,
+ GdkScreen *screen)
{
- GtkFileChooserButtonPrivate *priv;
- GtkFilePath *path;
-
- priv = GTK_FILE_CHOOSER_BUTTON_GET_PRIVATE (object);
-
- priv->dialog = dialog;
+ if (button->priv->settings_signal_id)
+ {
+ GtkSettings *settings;
- g_signal_connect (priv->dialog, "delete-event",
- G_CALLBACK (dialog_delete_event_cb), object);
- g_signal_connect (priv->dialog, "response",
- G_CALLBACK (dialog_response_cb), object);
+ settings = gtk_settings_get_for_screen (screen);
+ g_signal_handler_disconnect (settings,
+ button->priv->settings_signal_id);
+ button->priv->settings_signal_id = 0;
+ }
+}
- /* This is used, instead of the standard delegate, to ensure that signals are only
- * delegated when the OK button is pressed. */
- g_object_set_qdata (object, GTK_FILE_CHOOSER_DELEGATE_QUARK, priv->dialog);
- priv->dialog_folder_changed_id =
- g_signal_connect (priv->dialog, "current-folder-changed",
- G_CALLBACK (dialog_current_folder_changed_cb), object);
- priv->dialog_file_activated_id =
- g_signal_connect (priv->dialog, "file-activated",
- G_CALLBACK (dialog_file_activated_cb), object);
- priv->dialog_selection_changed_id =
- g_signal_connect (priv->dialog, "selection-changed",
- G_CALLBACK (dialog_selection_changed_cb), object);
- g_signal_connect (priv->dialog, "update-preview",
- G_CALLBACK (dialog_update_preview_cb), object);
- g_signal_connect (priv->dialog, "notify",
- G_CALLBACK (dialog_notify_cb), object);
- g_object_add_weak_pointer (G_OBJECT (priv->dialog),
- (gpointer *) (&priv->dialog));
+static GtkIconTheme *
+get_icon_theme (GtkWidget *widget)
+{
+ if (gtk_widget_has_screen (widget))
+ return gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
- /* Kinda ugly to set this here... */
- _gtk_file_chooser_entry_set_file_system (GTK_FILE_CHOOSER_ENTRY (priv->entry),
- _gtk_file_chooser_get_file_system (GTK_FILE_CHOOSER (priv->dialog)));
- path = gtk_file_path_new_steal ("/");
- _gtk_file_chooser_entry_set_base_folder (GTK_FILE_CHOOSER_ENTRY (priv->entry),
- path);
- priv->entry_changed_id = g_signal_connect_after (priv->entry, "changed",
- G_CALLBACK (entry_changed_cb),
- object);
+ return gtk_icon_theme_get_default ();
}
-
-static gchar *
-get_display_name (gchar *filename)
+static gboolean
+check_if_path_exists (GtkFileSystem *fs,
+ const GtkFilePath *path)
{
- const gchar *home_dir;
- gchar *tmp;
- gsize filename_len, home_dir_len;
+ gboolean path_exists;
+ GtkFilePath *parent_path;
- filename_len = strlen (filename);
+ path_exists = FALSE;
+ parent_path = NULL;
- if (g_file_test (filename, G_FILE_TEST_IS_DIR))
+ if (gtk_file_system_get_parent (fs, path, &parent_path, NULL))
{
- tmp = g_new (gchar, filename_len + 2);
- strcpy (tmp, filename);
- tmp[filename_len] = '/';
- tmp[filename_len + 1] = '\0';
- g_free (filename);
- filename = tmp;
+ GtkFileFolder *folder;
+
+ folder = gtk_file_system_get_folder (fs, parent_path, 0, NULL);
+ if (folder)
+ {
+ GtkFileInfo *info;
+
+ info = gtk_file_folder_get_info (folder, path, NULL);
+ if (info)
+ {
+ path_exists = TRUE;
+ gtk_file_info_free (info);
+ }
+
+ g_object_unref (folder);
+ }
+
+ gtk_file_path_free (parent_path);
}
- home_dir = g_get_home_dir ();
- if (home_dir != NULL)
+ return path_exists;
+}
+
+static void
+update_icons (GtkFileChooserButton *button)
+{
+ GtkFileChooserButtonPrivate *priv;
+ GdkPixbuf *pixbuf;
+ GSList *paths;
+
+ priv = GTK_FILE_CHOOSER_BUTTON_GET_PRIVATE (button);
+ pixbuf = NULL;
+ paths = _gtk_file_chooser_get_paths (GTK_FILE_CHOOSER (priv->dialog));
+
+ if (paths)
{
- home_dir_len = strlen (home_dir);
+ GtkFilePath *path;
+ GtkFileSystem *fs;
- if (strncmp (home_dir, filename, home_dir_len) == 0)
+ path = paths->data;
+ fs = _gtk_file_chooser_get_file_system (GTK_FILE_CHOOSER (priv->dialog));
+
+ switch (gtk_file_chooser_get_action (GTK_FILE_CHOOSER (priv->dialog)))
{
- tmp = g_build_filename ("~", filename + home_dir_len, NULL);
- g_free (filename);
- filename = tmp;
+ case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER:
+ {
+ GtkFileSystemVolume *volume;
+
+ volume = gtk_file_system_get_volume_for_path (fs, path);
+ if (volume)
+ {
+ GtkFilePath *base_path;
+
+ base_path = gtk_file_system_volume_get_base_path (fs, volume);
+
+ if (base_path && gtk_file_path_compare (base_path, path) == 0)
+ pixbuf = gtk_file_system_volume_render_icon (fs, volume,
+ GTK_WIDGET (button),
+ priv->icon_size,
+ NULL);
+
+ if (base_path)
+ gtk_file_path_free (base_path);
+
+ gtk_file_system_volume_free (fs, volume);
+ }
+ }
+
+ case GTK_FILE_CHOOSER_ACTION_OPEN:
+ if (!pixbuf)
+ pixbuf = gtk_file_system_render_icon (fs, path, GTK_WIDGET (button),
+ priv->icon_size, NULL);
+ break;
+
+ case GTK_FILE_CHOOSER_ACTION_SAVE:
+ if (check_if_path_exists (fs, path))
+ pixbuf = gtk_icon_theme_load_icon (get_icon_theme (GTK_WIDGET (button)),
+ GTK_STOCK_DIALOG_WARNING,
+ priv->icon_size, 0, NULL);
+ else
+ pixbuf = gtk_icon_theme_load_icon (get_icon_theme (GTK_WIDGET (button)),
+ NEW_FILE_ICON_NAME,
+ priv->icon_size, 0, NULL);
+ break;
+ case GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER:
+ if (check_if_path_exists (fs, path))
+ pixbuf = gtk_icon_theme_load_icon (get_icon_theme (GTK_WIDGET (button)),
+ GTK_STOCK_DIALOG_WARNING,
+ priv->icon_size, 0, NULL);
+ else
+ pixbuf = gtk_icon_theme_load_icon (get_icon_theme (GTK_WIDGET (button)),
+ NEW_DIR_ICON_NAME,
+ priv->icon_size, 0, NULL);
+ break;
}
+
+ gtk_file_paths_free (paths);
}
- return filename;
+ if (!pixbuf)
+ pixbuf = gtk_icon_theme_load_icon (get_icon_theme (GTK_WIDGET (button)),
+ FALLBACK_ICON_NAME,
+ priv->icon_size, 0, NULL);
+
+ gtk_image_set_from_pixbuf (GTK_IMAGE (priv->entry_image), pixbuf);
+ gtk_image_set_from_pixbuf (GTK_IMAGE (priv->label_image), pixbuf);
+
+ if (pixbuf)
+ g_object_unref (pixbuf);
}
static void
-update_entry (GtkFileChooserButton *button)
+update_label (GtkFileChooserButton *button)
{
- gchar *filename;
+ GtkFileChooserButtonPrivate *priv;
+ gchar *label_text;
+ GSList *paths;
+
+ priv = GTK_FILE_CHOOSER_BUTTON_GET_PRIVATE (button);
+ paths = _gtk_file_chooser_get_paths (GTK_FILE_CHOOSER (button->priv->dialog));
+ label_text = NULL;
- switch (gtk_file_chooser_get_action (GTK_FILE_CHOOSER (button->priv->dialog)))
+ if (paths)
{
- case GTK_FILE_CHOOSER_ACTION_OPEN:
- case GTK_FILE_CHOOSER_ACTION_SAVE:
- filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (button->priv->dialog));
- break;
- case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER:
- case GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER:
- filename = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (button->priv->dialog));
- break;
- default:
- g_assert_not_reached ();
- filename = NULL;
- break;
- }
+ GtkFileSystem *fs;
+ GtkFilePath *path;
+ GtkFileSystemVolume *volume;
+
+ path = paths->data;
- if (filename != NULL)
- filename = get_display_name (filename);
+ fs = _gtk_file_chooser_get_file_system (GTK_FILE_CHOOSER (priv->dialog));
- g_signal_handler_block (button->priv->entry, button->priv->entry_changed_id);
- if (filename != NULL)
- gtk_entry_set_text (GTK_ENTRY (button->priv->entry), filename);
- else
- gtk_entry_set_text (GTK_ENTRY (button->priv->entry), "");
- g_signal_handler_unblock (button->priv->entry, button->priv->entry_changed_id);
+ volume = gtk_file_system_get_volume_for_path (fs, path);
+ if (volume)
+ {
+ GtkFilePath *base_path;
+
+ base_path = gtk_file_system_volume_get_base_path (fs, volume);
+ if (base_path && gtk_file_path_compare (base_path, path) == 0)
+ label_text = gtk_file_system_volume_get_display_name (fs, volume);
+
+ if (base_path)
+ gtk_file_path_free (base_path);
+
+ gtk_file_system_volume_free (fs, volume);
+
+ if (label_text)
+ goto out;
+ }
+
+ if (gtk_file_system_path_is_local (fs, path))
+ {
+ const gchar *home;
+ gchar *tmp;
+ gchar *filename;
+
+ filename = gtk_file_system_path_to_filename (fs, path);
+
+ if (!filename)
+ goto out;
+
+ home = g_get_home_dir ();
+
+ /* Munging for psuedo-volumes and files in the user's home tree */
+ if (home)
+ {
+ if (strcmp (filename, home) == 0)
+ {
+ label_text = g_strdup (_("Home"));
+ goto localout;
+ }
+
+ tmp = g_build_filename (home, "Desktop", NULL);
+
+ if (strcmp (filename, tmp) == 0)
+ label_text = g_strdup (_("Desktop"));
+
+ g_free (tmp);
- if (filename != NULL)
- gtk_label_set_text (GTK_LABEL (button->priv->label), filename);
+ if (label_text)
+ goto out;
+
+ if (g_str_has_prefix (filename, home))
+ {
+ label_text = g_strconcat ("~", filename + strlen (home), NULL);
+ goto localout;
+ }
+ }
+
+ if (!label_text)
+ label_text = g_strdup (filename);
+
+ localout:
+ g_free (filename);
+ }
+ else
+ {
+ gchar *uri;
+
+ uri = gtk_file_system_path_to_uri (fs, path);
+
+ if (uri)
+ label_text = uri;
+ }
+
+ out:
+ gtk_file_paths_free (paths);
+ }
+
+ if (label_text)
+ {
+ gtk_label_set_text (GTK_LABEL (priv->label), label_text);
+ g_free (label_text);
+ }
else
- gtk_label_set_text (GTK_LABEL (button->priv->label), _(DEFAULT_FILENAME));
- g_free (filename);
+ gtk_label_set_text (GTK_LABEL (priv->label), _(DEFAULT_FILENAME));
}
-
-static gboolean
-update_dialog (gpointer user_data)
+static void
+update_entry (GtkFileChooserButton *button)
{
GtkFileChooserButtonPrivate *priv;
- const GtkFilePath *folder_path;
- const gchar *file_part;
- gchar *full_uri;
+ GSList *paths;
+ gchar *filename;
- priv = GTK_FILE_CHOOSER_BUTTON_GET_PRIVATE (user_data);
- folder_path =
- _gtk_file_chooser_entry_get_current_folder (GTK_FILE_CHOOSER_ENTRY (priv->entry));
- file_part =
- _gtk_file_chooser_entry_get_file_part (GTK_FILE_CHOOSER_ENTRY (priv->entry));
-
- if (folder_path != NULL)
- full_uri = g_build_filename (gtk_file_path_get_string (folder_path),
- file_part, NULL);
- else if (file_part != NULL)
- full_uri = g_build_filename ("file://", file_part, NULL);
- else
- full_uri = NULL;
+ priv = GTK_FILE_CHOOSER_BUTTON_GET_PRIVATE (button);
- if (full_uri != NULL)
- {
- gchar *display_name;
+ paths = _gtk_file_chooser_get_paths (GTK_FILE_CHOOSER (priv->dialog));
- display_name = g_filename_from_uri (full_uri, NULL, NULL);
- if (display_name)
+ if (paths)
+ {
+ GtkFileSystem *fs;
+ GtkFilePath *path;
+
+ path = paths->data;
+ fs = _gtk_file_chooser_get_file_system (GTK_FILE_CHOOSER (priv->dialog));
+
+ if (gtk_file_system_path_is_local (fs, path))
{
- display_name = get_display_name (display_name);
- gtk_label_set_text (GTK_LABEL (priv->label), display_name);
- g_free (display_name);
+ filename = gtk_file_system_path_to_filename (fs, path);
+
+ if (filename)
+ {
+ const gchar *home;
+ gchar *tmp;
+
+ if (g_file_test (filename, G_FILE_TEST_IS_DIR))
+ {
+ tmp = g_strconcat (filename, "/", NULL);
+ g_free (filename);
+ filename = tmp;
+ }
+
+ home = g_get_home_dir ();
+
+ if (home && g_str_has_prefix (filename, home))
+ {
+ tmp = g_strconcat ("~", filename + strlen (home), NULL);
+ g_free (filename);
+ filename = tmp;
+ }
+ }
}
+ else
+ filename = gtk_file_system_path_to_uri (fs, path);
}
else
+ filename = NULL;
+
+ if (filename)
{
- gtk_label_set_text (GTK_LABEL (priv->label), _(DEFAULT_FILENAME));
+ gchar *entry_text;
+
+ entry_text = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL);
+ g_free (filename);
+
+ gtk_entry_set_text (GTK_ENTRY (priv->entry), entry_text);
+ g_free (entry_text);
}
+ else
+ gtk_entry_set_text (GTK_ENTRY (priv->entry), "");
+}
+
+static void
+update_dialog (GtkFileChooserButton *button)
+{
+ GtkFileChooserButtonPrivate *priv;
+ GtkFilePath *current_folder;
+ GtkFileSystem *fs;
+ GtkFilePath *folder_part, *full_path;
+ gchar *file_part;
+ const gchar *text;
+ GtkFilePath *base_path;
+
+ priv = GTK_FILE_CHOOSER_BUTTON_GET_PRIVATE (button);
+ file_part = NULL;
+ folder_part = NULL;
+ fs = _gtk_file_chooser_get_file_system (GTK_FILE_CHOOSER (priv->dialog));
+
+ text = gtk_entry_get_text (GTK_ENTRY (priv->entry));
+
+ base_path = gtk_file_path_new_dup ("/");
+ gtk_file_system_parse (fs, base_path, text, &folder_part, &file_part, NULL);
+ gtk_file_path_free (base_path);
switch (gtk_file_chooser_get_action (GTK_FILE_CHOOSER (priv->dialog)))
{
case GTK_FILE_CHOOSER_ACTION_OPEN:
- if (folder_path != NULL)
+ gtk_file_chooser_unselect_all (GTK_FILE_CHOOSER (priv->dialog));
+ if (folder_part)
{
- GtkFileSystem *fs;
GtkFileFolder *folder;
- GtkFilePath *full_path;
GtkFileInfo *info;
- fs = _gtk_file_chooser_get_file_system (GTK_FILE_CHOOSER (priv->dialog));
- folder = gtk_file_system_get_folder (fs, folder_path,
+ folder = gtk_file_system_get_folder (fs, folder_part,
GTK_FILE_INFO_IS_FOLDER, NULL);
- full_path = gtk_file_system_make_path (fs, folder_path, file_part, NULL);
+ full_path = gtk_file_system_make_path (fs, folder_part, file_part, NULL);
info = gtk_file_folder_get_info (folder, full_path, NULL);
/* Entry contents don't exist. */
if (info == NULL)
_gtk_file_chooser_set_current_folder_path (GTK_FILE_CHOOSER (priv->dialog),
- folder_path, NULL);
+ folder_part, NULL);
/* Entry contents are a folder */
else if (gtk_file_info_get_is_folder (info))
_gtk_file_chooser_set_current_folder_path (GTK_FILE_CHOOSER (priv->dialog),
@@ -930,64 +1390,55 @@ update_dialog (gpointer user_data)
else
_gtk_file_chooser_select_path (GTK_FILE_CHOOSER (priv->dialog),
full_path, NULL);
-
+
if (info)
gtk_file_info_free (info);
+
gtk_file_path_free (full_path);
}
- else
- g_free (full_uri);
break;
case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER:
- if (folder_path != NULL)
+ gtk_file_chooser_unselect_all (GTK_FILE_CHOOSER (priv->dialog));
+ if (folder_part)
{
- GtkFileSystem *fs;
- GtkFilePath *full_path;
-
- fs = _gtk_file_chooser_get_file_system (GTK_FILE_CHOOSER (priv->dialog));
- full_path = gtk_file_system_make_path (fs, folder_path, file_part, NULL);
+ full_path = gtk_file_system_make_path (fs, folder_part, file_part, NULL);
/* Entry contents don't exist. */
- if (full_path != NULL)
+ if (full_path)
_gtk_file_chooser_select_path (GTK_FILE_CHOOSER (priv->dialog),
full_path, NULL);
else
_gtk_file_chooser_set_current_folder_path (GTK_FILE_CHOOSER (priv->dialog),
- folder_path, NULL);
+ folder_part, NULL);
gtk_file_path_free (full_path);
}
- else
- g_free (full_uri);
break;
case GTK_FILE_CHOOSER_ACTION_SAVE:
case GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER:
- if (folder_path != NULL)
- _gtk_file_chooser_set_current_folder_path (GTK_FILE_CHOOSER (priv->dialog),
- folder_path, NULL);
+ gtk_file_chooser_unselect_all (GTK_FILE_CHOOSER (priv->dialog));
+ if (folder_part)
+ {
+ current_folder = _gtk_file_chooser_get_current_folder_path (GTK_FILE_CHOOSER (priv->dialog));
+
+ if (!current_folder ||
+ gtk_file_path_compare (current_folder, folder_part) != 0)
+ {
+ _gtk_file_chooser_set_current_folder_path (GTK_FILE_CHOOSER (priv->dialog),
+ folder_part, NULL);
+ g_signal_emit_by_name (button, "current-folder-changed");
+ }
+
+ if (current_folder)
+ gtk_file_path_free (current_folder);
+ }
gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (priv->dialog),
file_part);
- g_free (full_uri);
+ g_signal_emit_by_name (button, "selection-changed");
break;
}
-
- priv->update_id = 0;
- return FALSE;
-}
-
-static gboolean
-update_dialog_idle (gpointer user_data)
-{
- gboolean result;
-
- GDK_THREADS_ENTER ();
- result = update_dialog (user_data);
- GDK_THREADS_LEAVE ();
-
- return result;
-
}
/* ************************ *
@@ -1001,7 +1452,6 @@ dialog_current_folder_changed_cb (GtkFileChooser *dialog,
g_signal_emit_by_name (user_data, "current-folder-changed");
}
-
static void
dialog_file_activated_cb (GtkFileChooser *dialog,
gpointer user_data)
@@ -1009,15 +1459,31 @@ dialog_file_activated_cb (GtkFileChooser *dialog,
g_signal_emit_by_name (user_data, "file-activated");
}
-
static void
dialog_selection_changed_cb (GtkFileChooser *dialog,
gpointer user_data)
{
+ GtkFileChooserButtonPrivate *priv;
+
+ priv = GTK_FILE_CHOOSER_BUTTON_GET_PRIVATE (user_data);
+
+ g_signal_handler_block (priv->entry, priv->entry_changed_id);
update_entry (user_data);
- g_signal_emit_by_name (user_data, "selection-changed");
+ g_signal_handler_unblock (priv->entry, priv->entry_changed_id);
+ update_icons (user_data);
+ update_label (user_data);
}
+static void
+dialog_selection_changed_proxy_cb (GtkFileChooser *dialog,
+ gpointer user_data)
+{
+ GtkFileChooserButtonPrivate *priv;
+
+ priv = GTK_FILE_CHOOSER_BUTTON_GET_PRIVATE (user_data);
+
+ g_signal_emit_by_name (user_data, "selection-changed");
+}
static void
dialog_update_preview_cb (GtkFileChooser *dialog,
@@ -1026,7 +1492,6 @@ dialog_update_preview_cb (GtkFileChooser *dialog,
g_signal_emit_by_name (user_data, "update-preview");
}
-
static void
dialog_notify_cb (GObject *dialog,
GParamSpec *pspec,
@@ -1040,7 +1505,6 @@ dialog_notify_cb (GObject *dialog,
g_object_notify (user_data, pspec->name);
}
-
static gboolean
dialog_delete_event_cb (GtkWidget *dialog,
GdkEvent *event,
@@ -1051,7 +1515,6 @@ dialog_delete_event_cb (GtkWidget *dialog,
return TRUE;
}
-
static void
dialog_response_cb (GtkFileChooser *dialog,
gint response,
@@ -1063,7 +1526,11 @@ dialog_response_cb (GtkFileChooser *dialog,
if (response == GTK_RESPONSE_ACCEPT)
{
+ g_signal_handler_block (priv->entry, priv->entry_changed_id);
update_entry (user_data);
+ g_signal_handler_unblock (priv->entry, priv->entry_changed_id);
+ update_label (user_data);
+ update_icons (user_data);
g_signal_emit_by_name (user_data, "current-folder-changed");
g_signal_emit_by_name (user_data, "selection-changed");
@@ -1110,7 +1577,7 @@ button_toggled_cb (GtkToggleButton *real_button,
g_signal_handler_block (priv->dialog,
priv->dialog_file_activated_id);
g_signal_handler_block (priv->dialog,
- priv->dialog_selection_changed_id);
+ priv->dialog_selection_changed_proxy_id);
gtk_widget_set_sensitive (priv->entry, FALSE);
gtk_window_present (GTK_WINDOW (priv->dialog));
}
@@ -1121,13 +1588,12 @@ button_toggled_cb (GtkToggleButton *real_button,
g_signal_handler_unblock (priv->dialog,
priv->dialog_file_activated_id);
g_signal_handler_unblock (priv->dialog,
- priv->dialog_selection_changed_id);
+ priv->dialog_selection_changed_proxy_id);
gtk_widget_set_sensitive (priv->entry, TRUE);
gtk_widget_hide (priv->dialog);
}
}
-
static void
button_notify_active_cb (GObject *real_button,
GParamSpec *pspec,
@@ -1137,26 +1603,57 @@ button_notify_active_cb (GObject *real_button,
}
-/* Ensure the button height == entry height */
-static void
-entry_size_allocate_cb (GtkWidget *entry,
- GtkAllocation *allocation,
- gpointer user_data)
+static gboolean
+update_idler (gpointer user_data)
{
- gtk_widget_set_size_request (user_data, -1, allocation->height);
-}
+ GtkFileChooserButtonPrivate *priv;
+ gboolean retval;
+
+ GDK_THREADS_ENTER ();
+ priv = GTK_FILE_CHOOSER_BUTTON_GET_PRIVATE (user_data);
+
+ if (!gtk_editable_get_selection_bounds (GTK_EDITABLE (priv->entry),
+ NULL, NULL))
+ {
+ g_signal_handler_block (priv->dialog,
+ priv->dialog_selection_changed_id);
+ update_dialog (user_data);
+ g_signal_handler_unblock (priv->dialog,
+ priv->dialog_selection_changed_id);
+ update_icons (user_data);
+ update_label (user_data);
+ priv->update_id = 0;
+ retval = FALSE;
+ }
+ else
+ retval = TRUE;
+
+ GDK_THREADS_LEAVE ();
+
+ return retval;
+}
static void
-entry_changed_cb (GtkEditable *chooser_entry,
+entry_changed_cb (GtkEditable *editable,
gpointer user_data)
{
GtkFileChooserButtonPrivate *priv;
priv = GTK_FILE_CHOOSER_BUTTON_GET_PRIVATE (user_data);
- /* We do this in an idle handler to avoid totally screwing up chooser_entry's
- * completion */
- if (priv->update_id != 0)
- priv->update_id = g_idle_add (update_dialog_idle, user_data);
+ if (priv->update_id)
+ g_source_remove (priv->update_id);
+
+ priv->update_id = g_idle_add_full (G_PRIORITY_LOW, update_idler,
+ user_data, NULL);
+}
+
+/* Ensure the button height == entry height */
+static void
+entry_size_allocate_cb (GtkWidget *entry,
+ GtkAllocation *allocation,
+ gpointer user_data)
+{
+ gtk_widget_set_size_request (user_data, -1, allocation->height);
}
diff --git a/gtk/gtkfilechooserbutton.h b/gtk/gtkfilechooserbutton.h
index ebbad4a170..780d73cbe8 100644
--- a/gtk/gtkfilechooserbutton.h
+++ b/gtk/gtkfilechooserbutton.h
@@ -80,7 +80,9 @@ void gtk_file_chooser_button_set_title (GtkFileChooserBu
gboolean gtk_file_chooser_button_get_active (GtkFileChooserButton *button);
void gtk_file_chooser_button_set_active (GtkFileChooserButton *button,
gboolean is_active);
-
+gint gtk_file_chooser_button_get_width_chars (GtkFileChooserButton *button);
+void gtk_file_chooser_button_set_width_chars (GtkFileChooserButton *button,
+ gint n_chars);
G_END_DECLS
diff --git a/gtk/gtklabel.c b/gtk/gtklabel.c
index fe60022204..7ae2fb0b95 100644
--- a/gtk/gtklabel.c
+++ b/gtk/gtklabel.c
@@ -42,6 +42,14 @@
#include "gtkstock.h"
#include "gtkbindings.h"
+#define GTK_LABEL_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_LABEL, GtkLabelPrivate))
+
+typedef struct
+{
+ gint width_chars;
+}
+GtkLabelPrivate;
+
struct _GtkLabelSelectionInfo
{
GdkWindow *window;
@@ -71,7 +79,8 @@ enum {
PROP_MNEMONIC_WIDGET,
PROP_CURSOR_POSITION,
PROP_SELECTION_BOUND,
- PROP_ELLIPSIZE
+ PROP_ELLIPSIZE,
+ PROP_WIDTH_CHARS
};
static guint signals[LAST_SIGNAL] = { 0 };
@@ -391,10 +400,10 @@ gtk_label_class_init (GtkLabelClass *class)
*
* Note that setting this property to a value other than %PANGO_ELLIPSIZE_NONE
* has the side-effect that the label requests only enough space to display the
- * ellipsis "...". Ellipsizing labels must be packed in a container which
- * ensures that the label gets a reasonable size allocated. In particular,
- * this means that ellipsizing labels don't work well in notebook tabs, unless
- * the tab's ::tab-expand property is set to %TRUE.
+ * ellipsis "...". In particular, this means that ellipsizing labels don't
+ * work well in notebook tabs, unless the tab's ::tab-expand property is set
+ * to %TRUE. Other means to set a label's width are
+ * gtk_widget_set_size_request() and gtk_label_set_width_chars().
*
* Since: 2.6
*/
@@ -406,6 +415,25 @@ gtk_label_class_init (GtkLabelClass *class)
PANGO_TYPE_ELLIPSIZE_MODE,
PANGO_ELLIPSIZE_NONE,
G_PARAM_READWRITE));
+
+ /**
+ * GtkLabel:width-chars:
+ *
+ * The desired width of the label, in characters. If this property is set to
+ * %-1, the width will be calculated automatically, otherwise the label will
+ * request either 3 characters or the property value, whichever is greater.
+ *
+ * Since: 2.6
+ **/
+ g_object_class_install_property (gobject_class,
+ PROP_WIDTH_CHARS,
+ g_param_spec_int ("width_chars",
+ P_("Width In Chararacters"),
+ P_("The desired width of the label, in characters"),
+ -1,
+ G_MAXINT,
+ -1,
+ G_PARAM_READWRITE));
/*
* Key bindings
@@ -483,6 +511,8 @@ gtk_label_class_init (GtkLabelClass *class)
/* copy */
gtk_binding_entry_add_signal (binding_set, GDK_c, GDK_CONTROL_MASK,
"copy_clipboard", 0);
+
+ g_type_class_add_private (class, sizeof (GtkLabelPrivate));
}
static void
@@ -527,6 +557,9 @@ gtk_label_set_property (GObject *object,
case PROP_ELLIPSIZE:
gtk_label_set_ellipsize (label, g_value_get_enum (value));
break;
+ case PROP_WIDTH_CHARS:
+ gtk_label_set_width_chars (label, g_value_get_int (value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -595,6 +628,9 @@ gtk_label_get_property (GObject *object,
case PROP_ELLIPSIZE:
g_value_set_enum (value, label->ellipsize);
break;
+ case PROP_WIDTH_CHARS:
+ g_value_set_enum (value, gtk_label_get_width_chars (label));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -605,8 +641,13 @@ gtk_label_get_property (GObject *object,
static void
gtk_label_init (GtkLabel *label)
{
+ GtkLabelPrivate *priv;
+
GTK_WIDGET_SET_FLAGS (label, GTK_NO_WINDOW);
-
+
+ priv = GTK_LABEL_GET_PRIVATE (label);
+ priv->width_chars = -1;
+
label->label = NULL;
label->jtype = GTK_JUSTIFY_LEFT;
@@ -1356,6 +1397,52 @@ gtk_label_get_ellipsize (GtkLabel *label)
}
/**
+ * gtk_label_set_width_chars:
+ * @label: a #GtkLabel
+ * @n_chars: the new desired width, in characters.
+ *
+ * Sets the desired width in characters of @label to @n_chars.
+ *
+ * Since: 2.6
+ **/
+void
+gtk_label_set_width_chars (GtkLabel *label,
+ gint n_chars)
+{
+ GtkLabelPrivate *priv;
+
+ g_return_if_fail (GTK_IS_LABEL (label));
+
+ priv = GTK_LABEL_GET_PRIVATE (label);
+
+ if (priv->width_chars != n_chars)
+ {
+ priv->width_chars = n_chars;
+ g_object_notify (G_OBJECT (label), "width-chars");
+ gtk_widget_queue_resize (GTK_WIDGET (label));
+ }
+}
+
+/**
+ * gtk_label_get_width_chars:
+ * @label: a #GtkLabel
+ *
+ * Retrieves the desired width of @label, in characters. See
+ * gtk_label_set_width_chars().
+ *
+ * Return value: the width of a label in characters.
+ *
+ * Since: 2.6
+ **/
+gint
+gtk_label_get_width_chars (GtkLabel *label)
+{
+ g_return_val_if_fail (GTK_IS_LABEL (label), -1);
+
+ return GTK_LABEL_GET_PRIVATE (label)->width_chars;
+}
+
+/**
* gtk_label_set_line_wrap:
* @label: a #GtkLabel
* @wrap: the setting
@@ -1624,6 +1711,7 @@ gtk_label_size_request (GtkWidget *widget,
GtkRequisition *requisition)
{
GtkLabel *label;
+ GtkLabelPrivate *priv;
gint width, height;
PangoRectangle logical_rect;
GtkWidgetAuxInfo *aux_info;
@@ -1632,6 +1720,7 @@ gtk_label_size_request (GtkWidget *widget,
g_return_if_fail (requisition != NULL);
label = GTK_LABEL (widget);
+ priv = GTK_LABEL_GET_PRIVATE (widget);
/*
* If word wrapping is on, then the height requisition can depend
@@ -1657,7 +1746,7 @@ gtk_label_size_request (GtkWidget *widget,
pango_layout_get_extents (label->layout, NULL, &logical_rect);
aux_info = _gtk_widget_get_aux_info (widget, FALSE);
- if (label->ellipsize)
+ if (label->ellipsize || priv->width_chars > 0)
{
PangoContext *context;
PangoFontMetrics *metrics;
@@ -1670,7 +1759,7 @@ gtk_label_size_request (GtkWidget *widget,
char_width = pango_font_metrics_get_approximate_char_width (metrics);
pango_font_metrics_unref (metrics);
- width += (PANGO_PIXELS (char_width) * 3);
+ width += (PANGO_PIXELS (char_width) * MAX (priv->width_chars, 3));
}
else
{
diff --git a/gtk/gtklabel.h b/gtk/gtklabel.h
index ef2d254ab5..9d71cd0b0a 100644
--- a/gtk/gtklabel.h
+++ b/gtk/gtklabel.h
@@ -132,6 +132,9 @@ GtkJustification gtk_label_get_justify (GtkLabel *label);
void gtk_label_set_ellipsize (GtkLabel *label,
PangoEllipsizeMode mode);
PangoEllipsizeMode gtk_label_get_ellipsize (GtkLabel *label);
+void gtk_label_set_width_chars (GtkLabel *label,
+ gint n_chars);
+gint gtk_label_get_width_chars (GtkLabel *label);
void gtk_label_set_pattern (GtkLabel *label,
const gchar *pattern);
void gtk_label_set_line_wrap (GtkLabel *label,
diff --git a/tests/.cvsignore b/tests/.cvsignore
index f23e825c6a..b3d7c26793 100644
--- a/tests/.cvsignore
+++ b/tests/.cvsignore
@@ -24,6 +24,7 @@ testfilechooserbutton
testgtk
testicontheme
testiconview
+testimage
testinput
testmenus
testmerge
diff --git a/tests/testfilechooserbutton.c b/tests/testfilechooserbutton.c
index d453e0f54d..cbf3eaea87 100644
--- a/tests/testfilechooserbutton.c
+++ b/tests/testfilechooserbutton.c
@@ -56,7 +56,7 @@ chooser_current_folder_changed_cb (GtkFileChooser *chooser, gpointer user_data)
folder = gtk_file_chooser_get_current_folder (chooser);
filename = gtk_file_chooser_get_filename (chooser);
- g_message ("%s:%s:\n`%s`\n\tFolder: `%s'\n\tFilename: `%s'", G_STRFUNC, G_STRLOC,
+ g_message ("%s::current-folder-changed\n\tFolder: `%s'\n\tFilename: `%s'\nDone.\n",
G_OBJECT_TYPE_NAME (chooser), folder, filename);
g_free (folder);
g_free (filename);
@@ -66,16 +66,12 @@ chooser_current_folder_changed_cb (GtkFileChooser *chooser, gpointer user_data)
static void
chooser_selection_changed_cb (GtkFileChooser *chooser, gpointer user_data)
{
- GSList *selection;
+ gchar *filename;
- g_message ("%s:%s:\n`%s` Selection:", G_STRFUNC, G_STRLOC, G_OBJECT_TYPE_NAME (chooser));
- for (selection = gtk_file_chooser_get_filenames (chooser); selection != NULL;
- selection = g_slist_remove_link (selection, selection))
- {
- g_print ("`%s'\n", (const gchar *) selection->data);
- g_free (selection->data);
- }
- g_print ("Done.\n");
+ filename = gtk_file_chooser_get_filename (chooser);
+ g_message ("%s::selection-changed\n\tSelection:`%s'\nDone.\n",
+ G_OBJECT_TYPE_NAME (chooser), filename);
+ g_free (filename);
}
@@ -86,7 +82,8 @@ chooser_file_activated_cb (GtkFileChooser *chooser, gpointer user_data)
folder = gtk_file_chooser_get_current_folder (chooser);
filename = gtk_file_chooser_get_filename (chooser);
- g_message ("%s:%s:\n`%s`\nFolder: `%s'\nFilename: `%s'", G_STRFUNC, G_STRLOC, G_OBJECT_TYPE_NAME (chooser), folder, filename);
+ g_message ("%s::file-activated\n\tFolder: `%s'\n\tFilename: `%s'\nDone.\n",
+ G_OBJECT_TYPE_NAME (chooser), folder, filename);
g_free (folder);
g_free (filename);
}
@@ -98,17 +95,17 @@ chooser_update_preview_cb (GtkFileChooser *chooser, gpointer user_data)
gchar *filename;
filename = gtk_file_chooser_get_preview_filename (chooser);
- g_message ("%s:%s:\n`%s`\nPreview Filename: `%s'", G_STRFUNC, G_STRLOC, G_OBJECT_TYPE_NAME (chooser), filename);
+ g_message ("%s::update-preview\n\tPreview Filename: `%s'\nDone.\n",
+ G_OBJECT_TYPE_NAME (chooser), filename);
g_free (filename);
}
-
int
main (int argc, char *argv[])
{
- GtkWidget *win, *vbox, *frame, *alignment, *group_box, *hbox, *label, *chooser, *button;
+ GtkWidget *win, *vbox, *frame, *alignment, *group_box;
+ GtkWidget *hbox, *label, *chooser, *button;
GtkSizeGroup *label_group;
-
gtk_init (&argc, &argv);
/* to test rtl layout, set RTL=1 in the environment */
@@ -138,15 +135,80 @@ main (int argc, char *argv[])
gtk_container_add (GTK_CONTAINER (alignment), group_box);
hbox = gtk_hbox_new (FALSE, 12);
- gtk_container_add (GTK_CONTAINER (group_box), hbox);
+ gtk_box_pack_start (GTK_BOX (group_box), hbox, FALSE, FALSE, 0);
label = gtk_label_new_with_mnemonic ("_Open:");
gtk_size_group_add_widget (GTK_SIZE_GROUP (label_group), label);
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
- chooser = gtk_file_chooser_button_new_with_backend ("Select A File - testfilechooserbutton",
- "gtk+");
+ chooser = gtk_file_chooser_button_new ("Select A File - testfilechooserbutton");
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser);
+ g_signal_connect (chooser, "current-folder-changed",
+ G_CALLBACK (chooser_current_folder_changed_cb), NULL);
+ g_signal_connect (chooser, "selection-changed", G_CALLBACK (chooser_selection_changed_cb), NULL);
+ g_signal_connect (chooser, "file-activated", G_CALLBACK (chooser_file_activated_cb), NULL);
+ g_signal_connect (chooser, "update-preview", G_CALLBACK (chooser_update_preview_cb), NULL);
+ gtk_container_add (GTK_CONTAINER (hbox), chooser);
+
+ button = gtk_button_new_with_label ("Properties...");
+ g_signal_connect (button, "clicked", G_CALLBACK (properties_button_clicked_cb), chooser);
+ gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
+
+ hbox = gtk_hbox_new (FALSE, 12);
+ gtk_box_pack_start (GTK_BOX (group_box), hbox, FALSE, FALSE, 0);
+
+ label = gtk_label_new_with_mnemonic ("Select _Folder:");
+ gtk_size_group_add_widget (GTK_SIZE_GROUP (label_group), label);
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+ gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+
+ chooser = gtk_file_chooser_button_new ("Select A File - testfilechooserbutton");
+ gtk_file_chooser_set_action (GTK_FILE_CHOOSER (chooser), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser);
+ g_signal_connect (chooser, "current-folder-changed",
+ G_CALLBACK (chooser_current_folder_changed_cb), NULL);
+ g_signal_connect (chooser, "selection-changed", G_CALLBACK (chooser_selection_changed_cb), NULL);
+ g_signal_connect (chooser, "file-activated", G_CALLBACK (chooser_file_activated_cb), NULL);
+ g_signal_connect (chooser, "update-preview", G_CALLBACK (chooser_update_preview_cb), NULL);
+ gtk_container_add (GTK_CONTAINER (hbox), chooser);
+
+ button = gtk_button_new_with_label ("Properties...");
+ g_signal_connect (button, "clicked", G_CALLBACK (properties_button_clicked_cb), chooser);
+ gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
+
+ hbox = gtk_hbox_new (FALSE, 12);
+ gtk_box_pack_start (GTK_BOX (group_box), hbox, FALSE, FALSE, 0);
+
+ label = gtk_label_new_with_mnemonic ("_Save:");
+ gtk_size_group_add_widget (GTK_SIZE_GROUP (label_group), label);
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+ gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+
+ chooser = gtk_file_chooser_button_new ("Select A File - testfilechooserbutton");
+ gtk_file_chooser_set_action (GTK_FILE_CHOOSER (chooser), GTK_FILE_CHOOSER_ACTION_SAVE);
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser);
+ g_signal_connect (chooser, "current-folder-changed",
+ G_CALLBACK (chooser_current_folder_changed_cb), NULL);
+ g_signal_connect (chooser, "selection-changed", G_CALLBACK (chooser_selection_changed_cb), NULL);
+ g_signal_connect (chooser, "file-activated", G_CALLBACK (chooser_file_activated_cb), NULL);
+ g_signal_connect (chooser, "update-preview", G_CALLBACK (chooser_update_preview_cb), NULL);
+ gtk_container_add (GTK_CONTAINER (hbox), chooser);
+
+ button = gtk_button_new_with_label ("Properties...");
+ g_signal_connect (button, "clicked", G_CALLBACK (properties_button_clicked_cb), chooser);
+ gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
+
+ hbox = gtk_hbox_new (FALSE, 12);
+ gtk_box_pack_start (GTK_BOX (group_box), hbox, FALSE, FALSE, 0);
+
+ label = gtk_label_new_with_mnemonic ("_Create Folder:");
+ gtk_size_group_add_widget (GTK_SIZE_GROUP (label_group), label);
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+ gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+
+ chooser = gtk_file_chooser_button_new ("Select A File - testfilechooserbutton");
+ gtk_file_chooser_set_action (GTK_FILE_CHOOSER (chooser), GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER);
gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser);
g_signal_connect (chooser, "current-folder-changed",
G_CALLBACK (chooser_current_folder_changed_cb), NULL);