Compare commits
115 Commits
fix-build-
...
async-colo
Author | SHA1 | Date | |
---|---|---|---|
|
35b0974000 | ||
|
4c18b1f345 | ||
|
48aa551a72 | ||
|
c20749e2d8 | ||
|
3e8a5bbb92 | ||
|
056022a54b | ||
|
1765bdc590 | ||
|
bcd9130548 | ||
|
a95cfb1c45 | ||
|
799fb41937 | ||
|
e6f4c596fa | ||
|
3d7fb26588 | ||
|
93f9b2d519 | ||
|
6f3613a06f | ||
|
3723778f42 | ||
|
3fc3f8d2ff | ||
|
2868f1b509 | ||
|
f44570e71a | ||
|
15d39dddc5 | ||
|
1028449bcc | ||
|
01cca279f9 | ||
|
a7cae4bffa | ||
|
3e2e29a1dc | ||
|
de069e15c2 | ||
|
f8edefd7c0 | ||
|
24a15b51fe | ||
|
1f7aba345d | ||
|
230212c59c | ||
|
86f7c19b91 | ||
|
e5cea4e39d | ||
|
22aca8952f | ||
|
c0e437d163 | ||
|
ffe97a453f | ||
|
c09ba28b06 | ||
|
81de43eba5 | ||
|
788be8b945 | ||
|
0370979225 | ||
|
943014074c | ||
|
c0e8523a01 | ||
|
8374ebe4c4 | ||
|
611d14108d | ||
|
25cf702345 | ||
|
1d9c61cada | ||
|
71adb26a0d | ||
|
e27fa33690 | ||
|
f7dfead861 | ||
|
aac04a0995 | ||
|
8af191e52d | ||
|
06382ff836 | ||
|
cd469788c3 | ||
|
44b5076cf2 | ||
|
e5be9e1035 | ||
|
b831d01f0d | ||
|
278bcf2680 | ||
|
c19d0dc9ea | ||
|
edd5ed169e | ||
|
8ec9c3fdc6 | ||
|
e95022040f | ||
|
3a2ce620e2 | ||
|
df49bf9eec | ||
|
53327f3aea | ||
|
c0c3d75062 | ||
|
d0d0409f9d | ||
|
3a7d094542 | ||
|
280adcbb8c | ||
|
83431a999c | ||
|
eeeee99aa8 | ||
|
0f503e0ba2 | ||
|
3e4ae62b44 | ||
|
ec4f814bd4 | ||
|
0141ba4e00 | ||
|
52ef16c21b | ||
|
6ca7104015 | ||
|
07d6166ab8 | ||
|
dc651c3dc3 | ||
|
f520801626 | ||
|
4e3fbd0b0f | ||
|
8a24fdea38 | ||
|
b26222b6ba | ||
|
c8d291ab86 | ||
|
0a87438432 | ||
|
ddf1cd6678 | ||
|
9c6d5e2ca5 | ||
|
1f2561b08e | ||
|
d5b31a30fd | ||
|
39c678988d | ||
|
9052c191cb | ||
|
766f442636 | ||
|
27a3d2d09e | ||
|
3a3482e41e | ||
|
44c37fa34a | ||
|
5c41dbfaa5 | ||
|
c9d2ff7a0f | ||
|
174af596c5 | ||
|
de2624faa7 | ||
|
cda784a5f4 | ||
|
cc33dbef03 | ||
|
ce36611c4e | ||
|
038cb31d27 | ||
|
3b53a6b0a9 | ||
|
619ff2338e | ||
|
2bcd6949df | ||
|
abd78ce5f5 | ||
|
7899fc03c4 | ||
|
9984f00781 | ||
|
a0d3bdc911 | ||
|
b96317b872 | ||
|
6c84958b9f | ||
|
f2559b1dbb | ||
|
ed2ade4801 | ||
|
4549172825 | ||
|
b877804eb6 | ||
|
5310abbcf7 | ||
|
490d4b0b9e | ||
|
230188fb30 |
@@ -11,7 +11,6 @@
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
|
||||
G_DECLARE_FINAL_TYPE (CanvasItem, canvas_item, CANVAS, ITEM, GtkWidget)
|
||||
|
||||
@@ -26,6 +25,9 @@ struct _CanvasItem {
|
||||
double delta;
|
||||
|
||||
GtkWidget *editor;
|
||||
|
||||
GtkStyleProvider *provider;
|
||||
char *css_class;
|
||||
};
|
||||
|
||||
struct _CanvasItemClass {
|
||||
@@ -36,32 +38,41 @@ G_DEFINE_TYPE (CanvasItem, canvas_item, GTK_TYPE_WIDGET)
|
||||
|
||||
static int n_items = 0;
|
||||
|
||||
static void
|
||||
unstyle_item (CanvasItem *item)
|
||||
{
|
||||
if (item->provider)
|
||||
{
|
||||
gtk_style_context_remove_provider_for_display (gtk_widget_get_display (item->label), item->provider);
|
||||
g_clear_object (&item->provider);
|
||||
}
|
||||
|
||||
if (item->css_class)
|
||||
{
|
||||
gtk_widget_remove_css_class (item->label, item->css_class);
|
||||
g_clear_pointer (&item->css_class, g_free);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_color (CanvasItem *item,
|
||||
GdkRGBA *color)
|
||||
{
|
||||
char *css;
|
||||
char *str;
|
||||
GtkStyleContext *context;
|
||||
GtkCssProvider *provider;
|
||||
const char *old_class;
|
||||
const char *name;
|
||||
|
||||
unstyle_item (item);
|
||||
|
||||
str = gdk_rgba_to_string (color);
|
||||
css = g_strdup_printf ("* { background: %s; }", str);
|
||||
|
||||
context = gtk_widget_get_style_context (item->label);
|
||||
provider = g_object_get_data (G_OBJECT (context), "style-provider");
|
||||
if (provider)
|
||||
gtk_style_context_remove_provider (context, GTK_STYLE_PROVIDER (provider));
|
||||
|
||||
old_class = (const char *)g_object_get_data (G_OBJECT (item->label), "css-class");
|
||||
if (old_class)
|
||||
gtk_widget_remove_css_class (item->label, old_class);
|
||||
name = gtk_widget_get_name (item->label);
|
||||
css = g_strdup_printf ("#%s { background: %s; }", name, str);
|
||||
|
||||
provider = gtk_css_provider_new ();
|
||||
gtk_css_provider_load_from_data (provider, css, -1);
|
||||
gtk_style_context_add_provider (gtk_widget_get_style_context (item->label), GTK_STYLE_PROVIDER (provider), 800);
|
||||
g_object_set_data_full (G_OBJECT (context), "style-provider", provider, g_object_unref);
|
||||
gtk_style_context_add_provider_for_display (gtk_widget_get_display (item->label), GTK_STYLE_PROVIDER (provider), 700);
|
||||
item->provider = GTK_STYLE_PROVIDER (provider);
|
||||
|
||||
g_free (str);
|
||||
g_free (css);
|
||||
@@ -71,21 +82,10 @@ static void
|
||||
set_css (CanvasItem *item,
|
||||
const char *class)
|
||||
{
|
||||
GtkStyleContext *context;
|
||||
GtkCssProvider *provider;
|
||||
const char *old_class;
|
||||
unstyle_item (item);
|
||||
|
||||
context = gtk_widget_get_style_context (item->label);
|
||||
provider = g_object_get_data (G_OBJECT (context), "style-provider");
|
||||
if (provider)
|
||||
gtk_style_context_remove_provider (context, GTK_STYLE_PROVIDER (provider));
|
||||
|
||||
old_class = (const char *)g_object_get_data (G_OBJECT (item->label), "css-class");
|
||||
if (old_class)
|
||||
gtk_widget_remove_css_class (item->label, old_class);
|
||||
|
||||
g_object_set_data_full (G_OBJECT (item->label), "css-class", g_strdup (class), g_free);
|
||||
gtk_widget_add_css_class (item->label, class);
|
||||
item->css_class = g_strdup (class);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -724,6 +724,7 @@ do_dnd (GtkWidget *do_widget)
|
||||
int i;
|
||||
int x, y;
|
||||
GtkCssProvider *provider;
|
||||
GString *css;
|
||||
|
||||
button = gtk_color_button_new ();
|
||||
g_object_unref (g_object_ref_sink (button));
|
||||
@@ -735,6 +736,18 @@ do_dnd (GtkWidget *do_widget)
|
||||
800);
|
||||
g_object_unref (provider);
|
||||
|
||||
css = g_string_new ("");
|
||||
for (i = 0; colors[i]; i++)
|
||||
g_string_append_printf (css, ".canvasitem.%s { background: %s; }\n", colors[i], colors[i]);
|
||||
|
||||
provider = gtk_css_provider_new ();
|
||||
gtk_css_provider_load_from_data (provider, css->str, css->len);
|
||||
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
|
||||
GTK_STYLE_PROVIDER (provider),
|
||||
800);
|
||||
g_object_unref (provider);
|
||||
g_string_free (css, TRUE);
|
||||
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
|
@@ -21,7 +21,75 @@
|
||||
#include "script-names.h"
|
||||
#include "language-names.h"
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
/* {{{ ScriptLang object */
|
||||
|
||||
G_DECLARE_FINAL_TYPE (ScriptLang, script_lang, SCRIPT, LANG, GObject)
|
||||
|
||||
struct _ScriptLang
|
||||
{
|
||||
GObject parent;
|
||||
|
||||
char *langname;
|
||||
unsigned int script_index;
|
||||
unsigned int lang_index;
|
||||
hb_tag_t lang_tag;
|
||||
};
|
||||
|
||||
struct _ScriptLangClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (ScriptLang, script_lang, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
script_lang_init (ScriptLang *self)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
script_lang_finalize (GObject *object)
|
||||
{
|
||||
ScriptLang *self = SCRIPT_LANG (object);
|
||||
|
||||
g_free (self->langname);
|
||||
|
||||
G_OBJECT_CLASS (script_lang_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
script_lang_class_init (ScriptLangClass *class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
|
||||
object_class->finalize = script_lang_finalize;
|
||||
}
|
||||
|
||||
static ScriptLang *
|
||||
script_lang_new (const char *langname,
|
||||
unsigned int script_index,
|
||||
unsigned int lang_index,
|
||||
hb_tag_t lang_tag)
|
||||
{
|
||||
ScriptLang *self;
|
||||
|
||||
self = g_object_new (script_lang_get_type (), NULL);
|
||||
|
||||
self->langname = g_strdup (langname);
|
||||
self->script_index = script_index;
|
||||
self->lang_index = lang_index;
|
||||
self->lang_tag = lang_tag;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
static char *
|
||||
script_lang_get_langname (ScriptLang *self)
|
||||
{
|
||||
return g_strdup (self->langname);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
#define MAKE_TAG(a,b,c,d) (unsigned int)(((a) << 24) | ((b) << 16) | ((c) << 8) | (d))
|
||||
|
||||
@@ -95,6 +163,10 @@ demo_free (gpointer data)
|
||||
g_clear_pointer (&demo->axes, g_hash_table_unref);
|
||||
g_clear_pointer (&demo->text, g_free);
|
||||
|
||||
gtk_style_context_remove_provider_for_display (gdk_display_get_default (),
|
||||
GTK_STYLE_PROVIDER (demo->provider));
|
||||
g_object_unref (demo->provider);
|
||||
|
||||
g_free (demo);
|
||||
}
|
||||
|
||||
@@ -472,8 +544,6 @@ update_display (void)
|
||||
GString *s;
|
||||
char *text;
|
||||
gboolean has_feature;
|
||||
GtkTreeIter iter;
|
||||
GtkTreeModel *model;
|
||||
PangoFontDescription *desc;
|
||||
GList *l;
|
||||
PangoAttrList *attrs;
|
||||
@@ -576,14 +646,13 @@ update_display (void)
|
||||
|
||||
features = g_string_free (s, FALSE);
|
||||
|
||||
if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (demo->script_lang), &iter))
|
||||
if (gtk_drop_down_get_selected (GTK_DROP_DOWN (demo->script_lang)) != 0)
|
||||
{
|
||||
hb_tag_t lang_tag;
|
||||
ScriptLang *selected;
|
||||
|
||||
model = gtk_combo_box_get_model (GTK_COMBO_BOX (demo->script_lang));
|
||||
gtk_tree_model_get (model, &iter, 3, &lang_tag, -1);
|
||||
selected = gtk_drop_down_get_selected_item (GTK_DROP_DOWN (demo->script_lang));
|
||||
|
||||
lang = pango_language_from_string (hb_language_to_string (hb_ot_tag_to_language (lang_tag)));
|
||||
lang = pango_language_from_string (hb_language_to_string (hb_ot_tag_to_language (selected->lang_tag)));
|
||||
}
|
||||
else
|
||||
lang = NULL;
|
||||
@@ -740,40 +809,30 @@ tag_pair_equal (gconstpointer a, gconstpointer b)
|
||||
return pair_a->script_tag == pair_b->script_tag && pair_a->lang_tag == pair_b->lang_tag;
|
||||
}
|
||||
|
||||
static int
|
||||
script_sort_func (GtkTreeModel *model,
|
||||
GtkTreeIter *a,
|
||||
GtkTreeIter *b,
|
||||
gpointer user_data)
|
||||
|
||||
static GtkOrdering
|
||||
script_sort (const void *item1,
|
||||
const void *item2,
|
||||
void *data)
|
||||
{
|
||||
char *sa, *sb;
|
||||
int ret;
|
||||
ScriptLang *a = (ScriptLang *)item1;
|
||||
ScriptLang *b = (ScriptLang *)item2;
|
||||
|
||||
gtk_tree_model_get (model, a, 0, &sa, -1);
|
||||
gtk_tree_model_get (model, b, 0, &sb, -1);
|
||||
|
||||
ret = strcmp (sa, sb);
|
||||
|
||||
g_free (sa);
|
||||
g_free (sb);
|
||||
|
||||
return ret;
|
||||
return strcmp (a->langname, b->langname);
|
||||
}
|
||||
|
||||
static void
|
||||
update_script_combo (void)
|
||||
{
|
||||
GtkListStore *store;
|
||||
GListStore *store;
|
||||
GtkSortListModel *sortmodel;
|
||||
hb_font_t *hb_font;
|
||||
int i, j, k;
|
||||
PangoFont *pango_font;
|
||||
GHashTable *tags;
|
||||
GHashTableIter iter;
|
||||
TagPair *pair;
|
||||
char *lang;
|
||||
hb_tag_t active;
|
||||
GtkTreeIter active_iter;
|
||||
gboolean have_active = FALSE;
|
||||
|
||||
lang = gtk_font_chooser_get_language (GTK_FONT_CHOOSER (demo->font));
|
||||
|
||||
@@ -783,7 +842,7 @@ update_script_combo (void)
|
||||
|
||||
g_free (lang);
|
||||
|
||||
store = gtk_list_store_new (4, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT);
|
||||
store = g_list_store_new (script_lang_get_type ());
|
||||
|
||||
pango_font = get_pango_font ();
|
||||
hb_font = pango_font_get_hb_font (pango_font);
|
||||
@@ -807,19 +866,19 @@ update_script_combo (void)
|
||||
|
||||
hb_face = hb_font_get_face (hb_font);
|
||||
|
||||
for (i= 0; i < 2; i++)
|
||||
for (guint i = 0; i < 2; i++)
|
||||
{
|
||||
hb_tag_t scripts[80];
|
||||
unsigned int script_count = G_N_ELEMENTS (scripts);
|
||||
|
||||
hb_ot_layout_table_get_script_tags (hb_face, tables[i], 0, &script_count, scripts);
|
||||
for (j = 0; j < script_count; j++)
|
||||
for (guint j = 0; j < script_count; j++)
|
||||
{
|
||||
hb_tag_t languages[80];
|
||||
unsigned int language_count = G_N_ELEMENTS (languages);
|
||||
|
||||
hb_ot_layout_script_get_language_tags (hb_face, tables[i], j, 0, &language_count, languages);
|
||||
for (k = 0; k < language_count; k++)
|
||||
for (guint k = 0; k < language_count; k++)
|
||||
{
|
||||
pair = g_new (TagPair, 1);
|
||||
pair->script_tag = scripts[j];
|
||||
@@ -839,7 +898,6 @@ update_script_combo (void)
|
||||
{
|
||||
const char *langname;
|
||||
char langbuf[5];
|
||||
GtkTreeIter tree_iter;
|
||||
|
||||
if (pair->lang_tag == 0 && pair->script_tag == 0)
|
||||
langname = NC_("Language", "None");
|
||||
@@ -856,31 +914,31 @@ update_script_combo (void)
|
||||
}
|
||||
}
|
||||
|
||||
gtk_list_store_insert_with_values (store, &tree_iter, -1,
|
||||
0, langname,
|
||||
1, pair->script_index,
|
||||
2, pair->lang_index,
|
||||
3, pair->lang_tag,
|
||||
-1);
|
||||
if (pair->lang_tag == active)
|
||||
{
|
||||
have_active = TRUE;
|
||||
active_iter = tree_iter;
|
||||
}
|
||||
g_list_store_append (store, script_lang_new (langname,
|
||||
pair->script_index,
|
||||
pair->lang_index,
|
||||
pair->lang_tag));
|
||||
}
|
||||
|
||||
g_hash_table_destroy (tags);
|
||||
|
||||
gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (store),
|
||||
script_sort_func, NULL, NULL);
|
||||
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store),
|
||||
GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
|
||||
GTK_SORT_ASCENDING);
|
||||
gtk_combo_box_set_model (GTK_COMBO_BOX (demo->script_lang), GTK_TREE_MODEL (store));
|
||||
if (have_active)
|
||||
gtk_combo_box_set_active_iter (GTK_COMBO_BOX (demo->script_lang), &active_iter);
|
||||
else
|
||||
gtk_combo_box_set_active_iter (GTK_COMBO_BOX (demo->script_lang), 0);
|
||||
sortmodel = gtk_sort_list_model_new (G_LIST_MODEL (store),
|
||||
GTK_SORTER (gtk_custom_sorter_new (script_sort, NULL, NULL)));
|
||||
gtk_drop_down_set_model (GTK_DROP_DOWN (demo->script_lang), G_LIST_MODEL (sortmodel));
|
||||
|
||||
for (guint i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (sortmodel)); i++)
|
||||
{
|
||||
ScriptLang *item = g_list_model_get_item (G_LIST_MODEL (sortmodel), i);
|
||||
g_object_unref (item);
|
||||
|
||||
if (item->lang_tag == active)
|
||||
{
|
||||
gtk_drop_down_set_selected (GTK_DROP_DOWN (demo->script_lang), i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_object_unref (sortmodel);
|
||||
}
|
||||
|
||||
static char *
|
||||
@@ -905,27 +963,19 @@ static void
|
||||
update_features (void)
|
||||
{
|
||||
int i, j;
|
||||
GtkTreeModel *model;
|
||||
GtkTreeIter iter;
|
||||
guint script_index, lang_index;
|
||||
hb_tag_t lang_tag;
|
||||
PangoFont *pango_font;
|
||||
hb_font_t *hb_font;
|
||||
GList *l;
|
||||
ScriptLang *selected;
|
||||
|
||||
/* set feature presence checks from the font features */
|
||||
|
||||
if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (demo->script_lang), &iter))
|
||||
if (gtk_drop_down_get_selected (GTK_DROP_DOWN (demo->script_lang)) == 0)
|
||||
return;
|
||||
|
||||
model = gtk_combo_box_get_model (GTK_COMBO_BOX (demo->script_lang));
|
||||
gtk_tree_model_get (model, &iter,
|
||||
1, &script_index,
|
||||
2, &lang_index,
|
||||
3, &lang_tag,
|
||||
-1);
|
||||
selected = gtk_drop_down_get_selected_item (GTK_DROP_DOWN (demo->script_lang));
|
||||
|
||||
if (lang_tag == 0) /* None is selected */
|
||||
if (selected->lang_tag == 0) /* None is selected */
|
||||
{
|
||||
for (l = demo->feature_items; l; l = l->next)
|
||||
{
|
||||
@@ -966,8 +1016,8 @@ update_features (void)
|
||||
|
||||
hb_ot_layout_language_get_feature_tags (hb_face,
|
||||
tables[i],
|
||||
script_index,
|
||||
lang_index,
|
||||
selected->script_index,
|
||||
selected->lang_index,
|
||||
0,
|
||||
&count,
|
||||
features);
|
||||
@@ -989,8 +1039,8 @@ update_features (void)
|
||||
|
||||
hb_ot_layout_language_find_feature (hb_face,
|
||||
tables[i],
|
||||
script_index,
|
||||
lang_index,
|
||||
selected->script_index,
|
||||
selected->lang_index,
|
||||
features[j],
|
||||
&feature_index);
|
||||
|
||||
@@ -1322,10 +1372,9 @@ free_instance (gpointer data)
|
||||
}
|
||||
|
||||
static void
|
||||
add_instance (hb_face_t *face,
|
||||
unsigned int index,
|
||||
GtkWidget *combo,
|
||||
int pos)
|
||||
add_instance (hb_face_t *face,
|
||||
unsigned int index,
|
||||
GtkStringList *strings)
|
||||
{
|
||||
Instance *instance;
|
||||
hb_ot_name_id_t name_id;
|
||||
@@ -1341,20 +1390,20 @@ add_instance (hb_face_t *face,
|
||||
instance->index = index;
|
||||
|
||||
g_hash_table_add (demo->instances, instance);
|
||||
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), instance->name);
|
||||
gtk_string_list_append (GTK_STRING_LIST (strings), instance->name);
|
||||
}
|
||||
|
||||
static void
|
||||
unset_instance (GtkAdjustment *adjustment)
|
||||
{
|
||||
if (demo->instance_combo)
|
||||
gtk_combo_box_set_active (GTK_COMBO_BOX (demo->instance_combo), 0);
|
||||
gtk_drop_down_set_selected (GTK_DROP_DOWN (demo->instance_combo), 0);
|
||||
}
|
||||
|
||||
static void
|
||||
instance_changed (GtkComboBox *combo)
|
||||
instance_changed (GtkDropDown *combo)
|
||||
{
|
||||
char *text;
|
||||
const char *text;
|
||||
Instance *instance;
|
||||
Instance ikey;
|
||||
int i;
|
||||
@@ -1366,11 +1415,12 @@ instance_changed (GtkComboBox *combo)
|
||||
hb_font_t *hb_font;
|
||||
hb_face_t *hb_face;
|
||||
|
||||
text = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (combo));
|
||||
text = gtk_string_list_get_string (GTK_STRING_LIST (gtk_drop_down_get_model (combo)),
|
||||
gtk_drop_down_get_selected (combo));
|
||||
if (text[0] == '\0')
|
||||
goto out;
|
||||
|
||||
ikey.name = text;
|
||||
ikey.name = (char *) text;
|
||||
instance = g_hash_table_lookup (demo->instances, &ikey);
|
||||
if (!instance)
|
||||
{
|
||||
@@ -1411,7 +1461,6 @@ instance_changed (GtkComboBox *combo)
|
||||
}
|
||||
|
||||
out:
|
||||
g_free (text);
|
||||
g_clear_object (&pango_font);
|
||||
g_free (ai);
|
||||
g_free (coords);
|
||||
@@ -1521,6 +1570,7 @@ update_font_variations (void)
|
||||
{
|
||||
GtkWidget *label;
|
||||
GtkWidget *combo;
|
||||
GtkStringList *strings;
|
||||
|
||||
label = gtk_label_new ("Instance");
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 0);
|
||||
@@ -1528,26 +1578,28 @@ update_font_variations (void)
|
||||
gtk_widget_set_valign (label, GTK_ALIGN_BASELINE);
|
||||
gtk_grid_attach (GTK_GRID (demo->variations_grid), label, 0, -1, 1, 1);
|
||||
|
||||
combo = gtk_combo_box_text_new ();
|
||||
strings = gtk_string_list_new (NULL);
|
||||
combo = gtk_drop_down_new (G_LIST_MODEL (strings), NULL);
|
||||
|
||||
gtk_widget_set_halign (combo, GTK_ALIGN_START);
|
||||
gtk_widget_set_valign (combo, GTK_ALIGN_BASELINE);
|
||||
|
||||
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "");
|
||||
gtk_string_list_append (strings, "");
|
||||
|
||||
for (i = 0; i < hb_ot_var_get_named_instance_count (hb_face); i++)
|
||||
add_instance (hb_face, i, combo, i);
|
||||
add_instance (hb_face, i, strings);
|
||||
|
||||
for (i = 0; i < hb_ot_var_get_named_instance_count (hb_face); i++)
|
||||
{
|
||||
if (matches_instance (hb_face, i, n_axes, design_coords))
|
||||
{
|
||||
gtk_combo_box_set_active (GTK_COMBO_BOX (combo), i + 1);
|
||||
gtk_drop_down_set_selected (GTK_DROP_DOWN (combo), i + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gtk_grid_attach (GTK_GRID (demo->variations_grid), combo, 1, -1, 3, 1);
|
||||
g_signal_connect (combo, "changed", G_CALLBACK (instance_changed), NULL);
|
||||
g_signal_connect (combo, "notify::selecte", G_CALLBACK (instance_changed), NULL);
|
||||
demo->instance_combo = combo;
|
||||
}
|
||||
|
||||
@@ -1694,6 +1746,7 @@ do_font_features (GtkWidget *do_widget)
|
||||
GtkBuilder *builder;
|
||||
GtkBuilderScope *scope;
|
||||
GtkEventController *controller;
|
||||
GtkExpression *expression;
|
||||
|
||||
builder = gtk_builder_new ();
|
||||
|
||||
@@ -1727,6 +1780,9 @@ do_font_features (GtkWidget *do_widget)
|
||||
demo->description = GTK_WIDGET (gtk_builder_get_object (builder, "description"));
|
||||
demo->font = GTK_WIDGET (gtk_builder_get_object (builder, "font"));
|
||||
demo->script_lang = GTK_WIDGET (gtk_builder_get_object (builder, "script_lang"));
|
||||
expression = gtk_cclosure_expression_new (G_TYPE_STRING, NULL, 0, NULL, G_CALLBACK (script_lang_get_langname), NULL, NULL);
|
||||
gtk_drop_down_set_expression (GTK_DROP_DOWN (demo->script_lang), expression);
|
||||
gtk_expression_unref (expression);
|
||||
demo->feature_list = GTK_WIDGET (gtk_builder_get_object (builder, "feature_list"));
|
||||
demo->stack = GTK_WIDGET (gtk_builder_get_object (builder, "stack"));
|
||||
demo->entry = GTK_WIDGET (gtk_builder_get_object (builder, "entry"));
|
||||
@@ -1745,8 +1801,8 @@ do_font_features (GtkWidget *do_widget)
|
||||
demo->swin = GTK_WIDGET (gtk_builder_get_object (builder, "swin"));
|
||||
|
||||
demo->provider = gtk_css_provider_new ();
|
||||
gtk_style_context_add_provider (gtk_widget_get_style_context (demo->swin),
|
||||
GTK_STYLE_PROVIDER (demo->provider), 800);
|
||||
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
|
||||
GTK_STYLE_PROVIDER (demo->provider), 800);
|
||||
|
||||
basic_value_changed (demo->size_adjustment, demo->size_entry);
|
||||
basic_value_changed (demo->letterspacing_adjustment, demo->letterspacing_entry);
|
||||
@@ -1824,3 +1880,5 @@ do_font_features (GtkWidget *do_widget)
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
/* vim:set foldmethod=marker expandtab: */
|
||||
|
@@ -259,16 +259,10 @@
|
||||
<object class="GtkBox" id="feature_list">
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkComboBox" id="script_lang">
|
||||
<object class="GtkDropDown" id="script_lang">
|
||||
<property name="tooltip-text" translatable="yes">Language System</property>
|
||||
<property name="margin-top">10</property>
|
||||
<signal name="changed" handler="font_features_script_changed" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkCellRendererText"/>
|
||||
<attributes>
|
||||
<attribute name="text">0</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
<signal name="notify::selected" handler="font_features_script_changed" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
@@ -10,8 +10,6 @@
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
|
||||
static GtkWidget *window = NULL;
|
||||
static GtkWidget *font_button = NULL;
|
||||
static GtkWidget *entry = NULL;
|
||||
@@ -45,7 +43,6 @@ update_image (void)
|
||||
cairo_t *cr;
|
||||
GdkPixbuf *pixbuf;
|
||||
GdkPixbuf *pixbuf2;
|
||||
const char *hint;
|
||||
cairo_font_options_t *fopt;
|
||||
cairo_hint_style_t hintstyle;
|
||||
cairo_hint_metrics_t hintmetrics;
|
||||
@@ -60,18 +57,23 @@ update_image (void)
|
||||
|
||||
fopt = cairo_font_options_copy (pango_cairo_context_get_font_options (context));
|
||||
|
||||
hint = gtk_combo_box_get_active_id (GTK_COMBO_BOX (hinting));
|
||||
hintstyle = CAIRO_HINT_STYLE_DEFAULT;
|
||||
if (hint)
|
||||
switch (gtk_drop_down_get_selected (GTK_DROP_DOWN (hinting)))
|
||||
{
|
||||
if (strcmp (hint, "none") == 0)
|
||||
hintstyle = CAIRO_HINT_STYLE_NONE;
|
||||
else if (strcmp (hint, "slight") == 0)
|
||||
hintstyle = CAIRO_HINT_STYLE_SLIGHT;
|
||||
else if (strcmp (hint, "medium") == 0)
|
||||
hintstyle = CAIRO_HINT_STYLE_MEDIUM;
|
||||
else if (strcmp (hint, "full") == 0)
|
||||
hintstyle = CAIRO_HINT_STYLE_FULL;
|
||||
case 0:
|
||||
hintstyle = CAIRO_HINT_STYLE_NONE;
|
||||
break;
|
||||
case 1:
|
||||
hintstyle = CAIRO_HINT_STYLE_SLIGHT;
|
||||
break;
|
||||
case 2:
|
||||
hintstyle = CAIRO_HINT_STYLE_MEDIUM;
|
||||
break;
|
||||
case 3:
|
||||
hintstyle = CAIRO_HINT_STYLE_FULL;
|
||||
break;
|
||||
default:
|
||||
hintstyle = CAIRO_HINT_STYLE_DEFAULT;
|
||||
break;
|
||||
}
|
||||
cairo_font_options_set_hint_style (fopt, hintstyle);
|
||||
|
||||
@@ -420,7 +422,7 @@ do_fontrendering (GtkWidget *do_widget)
|
||||
g_signal_connect (down_button, "clicked", G_CALLBACK (scale_down), NULL);
|
||||
g_signal_connect (entry, "notify::text", G_CALLBACK (update_image), NULL);
|
||||
g_signal_connect (font_button, "notify::font-desc", G_CALLBACK (update_image), NULL);
|
||||
g_signal_connect (hinting, "notify::active", G_CALLBACK (update_image), NULL);
|
||||
g_signal_connect (hinting, "notify::selected", G_CALLBACK (update_image), NULL);
|
||||
g_signal_connect (anti_alias, "notify::active", G_CALLBACK (update_image), NULL);
|
||||
g_signal_connect (hint_metrics, "notify::active", G_CALLBACK (update_image), NULL);
|
||||
g_signal_connect (text_radio, "notify::active", G_CALLBACK (update_image), NULL);
|
||||
|
@@ -116,15 +116,18 @@
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBoxText" id="hinting">
|
||||
<property name="active">0</property>
|
||||
<object class="GtkDropDown" id="hinting">
|
||||
<property name="valign">center</property>
|
||||
<items>
|
||||
<item translatable="yes" id="none">None</item>
|
||||
<item translatable="yes" id="slight">Slight</item>
|
||||
<item translatable="yes" id="medium">Medium</item>
|
||||
<item translatable="yes" id="full">Full</item>
|
||||
</items>
|
||||
<property name="model">
|
||||
<object class="GtkStringList">
|
||||
<items>
|
||||
<item translatable="yes">None</item>
|
||||
<item translatable="yes">Slight</item>
|
||||
<item translatable="yes">Medium</item>
|
||||
<item translatable="yes">Full</item>
|
||||
</items>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
<layout>
|
||||
|
@@ -20,8 +20,6 @@
|
||||
#include "gtkshadertoy.h"
|
||||
#include "gskshaderpaintable.h"
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
|
||||
static GtkWidget *demo_window = NULL;
|
||||
|
||||
static void
|
||||
@@ -146,7 +144,6 @@ make_shader_stack (const char *name,
|
||||
GtkTextBuffer *buffer;
|
||||
GBytes *bytes;
|
||||
GtkEventController *controller;
|
||||
GtkCssProvider *provider;
|
||||
GdkPaintable *paintable;
|
||||
|
||||
stack = gtk_shader_stack_new ();
|
||||
@@ -237,12 +234,6 @@ make_shader_stack (const char *name,
|
||||
g_signal_connect (buffer, "changed", G_CALLBACK (text_changed), button);
|
||||
g_object_set_data (G_OBJECT (button), "the-stack", stack);
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (apply_text), buffer);
|
||||
provider = gtk_css_provider_new ();
|
||||
gtk_css_provider_load_from_data (provider, "button.small { padding: 0; }", -1);
|
||||
gtk_style_context_add_provider (gtk_widget_get_style_context (button),
|
||||
GTK_STYLE_PROVIDER (provider),
|
||||
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
|
||||
g_object_unref (provider);
|
||||
gtk_widget_set_halign (button, GTK_ALIGN_CENTER);
|
||||
gtk_widget_set_valign (button, GTK_ALIGN_CENTER);
|
||||
gtk_widget_add_css_class (button, "small");
|
||||
@@ -276,11 +267,21 @@ make_shader_stack (const char *name,
|
||||
return vbox;
|
||||
}
|
||||
|
||||
static void
|
||||
remove_provider (gpointer data)
|
||||
{
|
||||
GtkStyleProvider *provider = GTK_STYLE_PROVIDER (data);
|
||||
|
||||
gtk_style_context_remove_provider_for_display (gdk_display_get_default (), provider);
|
||||
g_object_unref (provider);
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
create_gltransition_window (GtkWidget *do_widget)
|
||||
{
|
||||
GtkWidget *window, *headerbar, *scale, *outer_grid, *grid, *background;
|
||||
GdkPaintable *paintable;
|
||||
GtkCssProvider *provider;
|
||||
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
|
||||
@@ -335,6 +336,14 @@ create_gltransition_window (GtkWidget *do_widget)
|
||||
make_shader_stack ("Kaleidoscope", "/gltransition/kaleidoscope.glsl", 3, scale),
|
||||
1, 1, 1, 1);
|
||||
|
||||
provider = gtk_css_provider_new ();
|
||||
gtk_css_provider_load_from_data (provider, "button.small { padding: 0; }", -1);
|
||||
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
|
||||
GTK_STYLE_PROVIDER (provider),
|
||||
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
|
||||
|
||||
g_object_set_data_full (G_OBJECT (window), "provider", provider, remove_provider);
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
|
@@ -10,8 +10,6 @@
|
||||
#include "script-names.h"
|
||||
#include "unicode-names.h"
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
|
||||
#define UCD_TYPE_ITEM (ucd_item_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (UcdItem, ucd_item, UCD, ITEM, GObject)
|
||||
|
||||
@@ -339,6 +337,15 @@ create_ucd_view (GtkWidget *label)
|
||||
|
||||
static GtkWidget *window;
|
||||
|
||||
static void
|
||||
remove_provider (gpointer data)
|
||||
{
|
||||
GtkStyleProvider *provider = GTK_STYLE_PROVIDER (data);
|
||||
|
||||
gtk_style_context_remove_provider_for_display (gdk_display_get_default (), provider);
|
||||
g_object_unref (provider);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_listview_ucd (GtkWidget *do_widget)
|
||||
{
|
||||
@@ -361,7 +368,7 @@ do_listview_ucd (GtkWidget *do_widget)
|
||||
gtk_widget_add_css_class (label, "enormous");
|
||||
provider = gtk_css_provider_new ();
|
||||
gtk_css_provider_load_from_data (provider, "label.enormous { font-size: 80px; }", -1);
|
||||
gtk_style_context_add_provider (gtk_widget_get_style_context (label), GTK_STYLE_PROVIDER (provider), 800);
|
||||
gtk_style_context_add_provider_for_display (gdk_display_get_default (), GTK_STYLE_PROVIDER (provider), 800);
|
||||
gtk_widget_set_hexpand (label, TRUE);
|
||||
gtk_box_append (GTK_BOX (box), label);
|
||||
|
||||
@@ -371,6 +378,8 @@ do_listview_ucd (GtkWidget *do_widget)
|
||||
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), listview);
|
||||
gtk_box_prepend (GTK_BOX (box), sw);
|
||||
gtk_window_set_child (GTK_WINDOW (window), box);
|
||||
|
||||
g_object_set_data_full (G_OBJECT (window), "provider", provider, remove_provider);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
|
@@ -8,7 +8,6 @@
|
||||
#include "config.h"
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
|
||||
/* Create an object for the pegs that get moved around in the game.
|
||||
*
|
||||
@@ -361,6 +360,15 @@ drop_drop (GtkDropTarget *target,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
remove_provider (gpointer data)
|
||||
{
|
||||
GtkStyleProvider *provider = GTK_STYLE_PROVIDER (data);
|
||||
|
||||
gtk_style_context_remove_provider_for_display (gdk_display_get_default (), provider);
|
||||
g_object_unref (provider);
|
||||
}
|
||||
|
||||
static void
|
||||
create_board (GtkWidget *window)
|
||||
{
|
||||
@@ -377,6 +385,9 @@ create_board (GtkWidget *window)
|
||||
|
||||
provider = gtk_css_provider_new ();
|
||||
gtk_css_provider_load_from_data (provider, css, -1);
|
||||
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
|
||||
GTK_STYLE_PROVIDER (provider),
|
||||
800);
|
||||
|
||||
grid = gtk_grid_new ();
|
||||
gtk_widget_set_halign (grid, GTK_ALIGN_CENTER);
|
||||
@@ -395,9 +406,6 @@ create_board (GtkWidget *window)
|
||||
continue;
|
||||
|
||||
image = gtk_image_new ();
|
||||
gtk_style_context_add_provider (gtk_widget_get_style_context (image),
|
||||
GTK_STYLE_PROVIDER (provider),
|
||||
800);
|
||||
gtk_widget_add_css_class (image, "solitaire-field");
|
||||
gtk_image_set_icon_size (GTK_IMAGE (image), GTK_ICON_SIZE_LARGE);
|
||||
if (x != 3 || y != 3)
|
||||
@@ -441,7 +449,7 @@ create_board (GtkWidget *window)
|
||||
}
|
||||
}
|
||||
|
||||
g_object_unref (provider);
|
||||
g_object_set_data_full (G_OBJECT (window), "provider", provider, remove_provider);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@@ -16,7 +16,6 @@ enum {
|
||||
NUM_PROPERTIES
|
||||
};
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
|
||||
static void
|
||||
pixbuf_paintable_snapshot (GdkPaintable *paintable,
|
||||
GdkSnapshot *snapshot,
|
||||
@@ -37,7 +36,6 @@ pixbuf_paintable_snapshot (GdkPaintable *paintable,
|
||||
|
||||
g_object_unref (texture);
|
||||
}
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS;
|
||||
|
||||
static int
|
||||
pixbuf_paintable_get_intrinsic_width (GdkPaintable *paintable)
|
||||
|
@@ -16,26 +16,6 @@
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
|
||||
/* Convenience function to create a combo box holding a number of strings
|
||||
*/
|
||||
GtkWidget *
|
||||
create_combo_box (const char **strings)
|
||||
{
|
||||
GtkWidget *combo_box;
|
||||
const char **str;
|
||||
|
||||
combo_box = gtk_combo_box_text_new ();
|
||||
|
||||
for (str = strings; *str; str++)
|
||||
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo_box), *str);
|
||||
|
||||
gtk_combo_box_set_active (GTK_COMBO_BOX (combo_box), 0);
|
||||
|
||||
return combo_box;
|
||||
}
|
||||
|
||||
static void
|
||||
add_row (GtkGrid *table,
|
||||
int row,
|
||||
@@ -43,7 +23,7 @@ add_row (GtkGrid *table,
|
||||
const char *label_text,
|
||||
const char **options)
|
||||
{
|
||||
GtkWidget *combo_box;
|
||||
GtkWidget *dropdown;
|
||||
GtkWidget *label;
|
||||
|
||||
label = gtk_label_new_with_mnemonic (label_text);
|
||||
@@ -52,12 +32,12 @@ add_row (GtkGrid *table,
|
||||
gtk_widget_set_hexpand (label, TRUE);
|
||||
gtk_grid_attach (table, label, 0, row, 1, 1);
|
||||
|
||||
combo_box = create_combo_box (options);
|
||||
gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo_box);
|
||||
gtk_widget_set_halign (combo_box, GTK_ALIGN_END);
|
||||
gtk_widget_set_valign (combo_box, GTK_ALIGN_BASELINE);
|
||||
gtk_size_group_add_widget (size_group, combo_box);
|
||||
gtk_grid_attach (table, combo_box, 1, row, 1, 1);
|
||||
dropdown = gtk_drop_down_new_from_strings (options);
|
||||
gtk_label_set_mnemonic_widget (GTK_LABEL (label), dropdown);
|
||||
gtk_widget_set_halign (dropdown, GTK_ALIGN_END);
|
||||
gtk_widget_set_valign (dropdown, GTK_ALIGN_BASELINE);
|
||||
gtk_size_group_add_widget (size_group, dropdown);
|
||||
gtk_grid_attach (table, dropdown, 1, row, 1, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@@ -11,7 +11,6 @@
|
||||
#include <stdlib.h> /* for exit() */
|
||||
#include "paintable.h"
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
|
||||
static void easter_egg_callback (GtkWidget *button, gpointer data);
|
||||
|
||||
@@ -431,11 +430,11 @@ attach_widgets (GtkTextView *text_view)
|
||||
}
|
||||
else if (i == 1)
|
||||
{
|
||||
widget = gtk_combo_box_text_new ();
|
||||
const char *options[] = {
|
||||
"Option 1", "Option 2", "Option 3", NULL
|
||||
};
|
||||
|
||||
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (widget), "Option 1");
|
||||
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (widget), "Option 2");
|
||||
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (widget), "Option 3");
|
||||
widget = gtk_drop_down_new_from_strings (options);
|
||||
}
|
||||
else if (i == 2)
|
||||
{
|
||||
|
@@ -1,8 +1,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GtkApplication parent_instance;
|
||||
@@ -352,7 +350,8 @@ quit_activated (GSimpleAction *action,
|
||||
}
|
||||
|
||||
static void
|
||||
combo_changed (GtkComboBox *combo,
|
||||
combo_changed (GtkDropDown *combo,
|
||||
GParamSpec *pspec,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkDialog *dialog = user_data;
|
||||
@@ -361,7 +360,7 @@ combo_changed (GtkComboBox *combo,
|
||||
char **accels;
|
||||
char *str;
|
||||
|
||||
action = gtk_combo_box_get_active_id (combo);
|
||||
action = gtk_string_object_get_string (GTK_STRING_OBJECT (gtk_drop_down_get_selected_item (combo)));
|
||||
|
||||
if (!action)
|
||||
return;
|
||||
@@ -390,7 +389,7 @@ response (GtkDialog *dialog,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkEntry *entry = g_object_get_data (user_data, "entry");
|
||||
GtkComboBox *combo = g_object_get_data (user_data, "combo");
|
||||
GtkDropDown *combo = g_object_get_data (user_data, "combo");
|
||||
const char *action;
|
||||
const char *str;
|
||||
char **accels;
|
||||
@@ -401,7 +400,7 @@ response (GtkDialog *dialog,
|
||||
return;
|
||||
}
|
||||
|
||||
action = gtk_combo_box_get_active_id (combo);
|
||||
action = gtk_string_object_get_string (GTK_STRING_OBJECT (gtk_drop_down_get_selected_item (combo)));
|
||||
|
||||
if (!action)
|
||||
return;
|
||||
@@ -426,6 +425,7 @@ edit_accels (GSimpleAction *action,
|
||||
char **actions;
|
||||
GtkWidget *dialog;
|
||||
int i;
|
||||
GtkStringList *strings;
|
||||
|
||||
dialog = gtk_dialog_new_with_buttons ("Accelerators",
|
||||
NULL,
|
||||
@@ -437,7 +437,8 @@ edit_accels (GSimpleAction *action,
|
||||
gtk_window_set_application (GTK_WINDOW (dialog), app);
|
||||
actions = gtk_application_list_action_descriptions (app);
|
||||
|
||||
combo = gtk_combo_box_text_new ();
|
||||
strings = gtk_string_list_new (NULL);
|
||||
combo = gtk_drop_down_new (G_LIST_MODEL (strings), NULL);
|
||||
g_object_set (gtk_dialog_get_content_area (GTK_DIALOG (dialog)),
|
||||
"margin-top", 10,
|
||||
"margin-bottom", 10,
|
||||
@@ -448,8 +449,8 @@ edit_accels (GSimpleAction *action,
|
||||
|
||||
gtk_box_append (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), combo);
|
||||
for (i = 0; actions[i]; i++)
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), actions[i], actions[i]);
|
||||
g_signal_connect (combo, "changed", G_CALLBACK (combo_changed), dialog);
|
||||
gtk_string_list_append (strings, actions[i]);
|
||||
g_signal_connect (combo, "notify::selected", G_CALLBACK (combo_changed), dialog);
|
||||
|
||||
entry = gtk_entry_new ();
|
||||
gtk_widget_set_hexpand (entry, TRUE);
|
||||
@@ -460,7 +461,7 @@ edit_accels (GSimpleAction *action,
|
||||
g_object_set_data (G_OBJECT (dialog), "combo", combo);
|
||||
g_object_set_data (G_OBJECT (dialog), "entry", entry);
|
||||
|
||||
gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
|
||||
gtk_drop_down_set_selected (GTK_DROP_DOWN (combo), 0);
|
||||
|
||||
gtk_widget_show (dialog);
|
||||
}
|
||||
|
@@ -436,6 +436,7 @@ gtk_entry_completion_init (GtkEntryCompletion *completion)
|
||||
completion->inline_selection = FALSE;
|
||||
|
||||
completion->filter_model = NULL;
|
||||
completion->insert_text_signal_group = NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -1384,13 +1385,12 @@ gtk_entry_completion_insert_completion_text (GtkEntryCompletion *completion,
|
||||
{
|
||||
int len;
|
||||
GtkText *text = gtk_entry_get_text_widget (GTK_ENTRY (completion->entry));
|
||||
GtkEntryBuffer *buffer = gtk_text_get_buffer (text);
|
||||
|
||||
if (completion->changed_id > 0)
|
||||
g_signal_handler_block (text, completion->changed_id);
|
||||
|
||||
if (completion->insert_text_id > 0)
|
||||
g_signal_handler_block (buffer, completion->insert_text_id);
|
||||
if (completion->insert_text_signal_group != NULL)
|
||||
g_signal_group_block (completion->insert_text_signal_group);
|
||||
|
||||
gtk_editable_set_text (GTK_EDITABLE (completion->entry), new_text);
|
||||
|
||||
@@ -1400,8 +1400,8 @@ gtk_entry_completion_insert_completion_text (GtkEntryCompletion *completion,
|
||||
if (completion->changed_id > 0)
|
||||
g_signal_handler_unblock (text, completion->changed_id);
|
||||
|
||||
if (completion->insert_text_id > 0)
|
||||
g_signal_handler_unblock (buffer, completion->insert_text_id);
|
||||
if (completion->insert_text_signal_group != NULL)
|
||||
g_signal_group_unblock (completion->insert_text_signal_group);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -1440,11 +1440,9 @@ gtk_entry_completion_insert_prefix (GtkEntryCompletion *completion)
|
||||
|
||||
gboolean done;
|
||||
char *prefix;
|
||||
GtkText *text = gtk_entry_get_text_widget (GTK_ENTRY (completion->entry));
|
||||
GtkEntryBuffer *buffer = gtk_text_get_buffer (text);
|
||||
|
||||
if (completion->insert_text_id > 0)
|
||||
g_signal_handler_block (buffer, completion->insert_text_id);
|
||||
if (completion->insert_text_signal_group != NULL)
|
||||
g_signal_group_block (completion->insert_text_signal_group);
|
||||
|
||||
prefix = gtk_entry_completion_compute_prefix (completion,
|
||||
gtk_editable_get_text (GTK_EDITABLE (completion->entry)));
|
||||
@@ -1456,8 +1454,8 @@ gtk_entry_completion_insert_prefix (GtkEntryCompletion *completion)
|
||||
g_free (prefix);
|
||||
}
|
||||
|
||||
if (completion->insert_text_id > 0)
|
||||
g_signal_handler_unblock (buffer, completion->insert_text_id);
|
||||
if (completion->insert_text_signal_group != NULL)
|
||||
g_signal_group_unblock (completion->insert_text_signal_group);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2098,7 +2096,6 @@ connect_completion_signals (GtkEntryCompletion *completion)
|
||||
{
|
||||
GtkEventController *controller;
|
||||
GtkText *text = gtk_entry_get_text_widget (GTK_ENTRY (completion->entry));
|
||||
GtkEntryBuffer *buffer = gtk_text_get_buffer (text);
|
||||
|
||||
controller = completion->entry_key_controller = gtk_event_controller_key_new ();
|
||||
gtk_event_controller_set_static_name (controller, "gtk-entry-completion");
|
||||
@@ -2113,8 +2110,10 @@ connect_completion_signals (GtkEntryCompletion *completion)
|
||||
completion->changed_id =
|
||||
g_signal_connect (text, "changed", G_CALLBACK (gtk_entry_completion_changed), completion);
|
||||
|
||||
completion->insert_text_id =
|
||||
g_signal_connect (buffer, "inserted-text", G_CALLBACK (completion_inserted_text_callback), completion);
|
||||
completion->insert_text_signal_group = g_signal_group_new (GTK_TYPE_ENTRY_BUFFER);
|
||||
g_signal_group_connect (completion->insert_text_signal_group, "inserted-text", G_CALLBACK (completion_inserted_text_callback), completion);
|
||||
g_object_bind_property (text, "buffer", completion->insert_text_signal_group, "target", G_BINDING_SYNC_CREATE);
|
||||
|
||||
g_signal_connect (text, "notify", G_CALLBACK (clear_completion_callback), completion);
|
||||
g_signal_connect_swapped (text, "activate", G_CALLBACK (accept_completion_callback), completion);
|
||||
}
|
||||
@@ -2123,7 +2122,6 @@ static void
|
||||
disconnect_completion_signals (GtkEntryCompletion *completion)
|
||||
{
|
||||
GtkText *text = gtk_entry_get_text_widget (GTK_ENTRY (completion->entry));
|
||||
GtkEntryBuffer *buffer = gtk_text_get_buffer (text);
|
||||
|
||||
gtk_widget_remove_controller (GTK_WIDGET (text), completion->entry_key_controller);
|
||||
gtk_widget_remove_controller (GTK_WIDGET (text), completion->entry_focus_controller);
|
||||
@@ -2134,12 +2132,9 @@ disconnect_completion_signals (GtkEntryCompletion *completion)
|
||||
g_signal_handler_disconnect (text, completion->changed_id);
|
||||
completion->changed_id = 0;
|
||||
}
|
||||
if (completion->insert_text_id > 0 &&
|
||||
g_signal_handler_is_connected (buffer, completion->insert_text_id))
|
||||
{
|
||||
g_signal_handler_disconnect (buffer, completion->insert_text_id);
|
||||
completion->insert_text_id = 0;
|
||||
}
|
||||
|
||||
g_clear_object (&completion->insert_text_signal_group);
|
||||
|
||||
g_signal_handlers_disconnect_by_func (text, G_CALLBACK (clear_completion_callback), completion);
|
||||
g_signal_handlers_disconnect_by_func (text, G_CALLBACK (accept_completion_callback), completion);
|
||||
}
|
||||
|
@@ -78,16 +78,20 @@
|
||||
#include <gtk/gtkcenterbox.h>
|
||||
#include <gtk/gtkcenterlayout.h>
|
||||
#include <gtk/gtkcheckbutton.h>
|
||||
#include <gtk/gtkchoice.h>
|
||||
#include <gtk/gtkcolorbutton.h>
|
||||
#include <gtk/gtkcolorchooser.h>
|
||||
#include <gtk/gtkcolorchooserdialog.h>
|
||||
#include <gtk/gtkcolorchooserwidget.h>
|
||||
#include <gtk/gtkcolordialog.h>
|
||||
#include <gtk/gtkcolordialogbutton.h>
|
||||
#include <gtk/gtkcolorutils.h>
|
||||
#include <gtk/gtkcolumnview.h>
|
||||
#include <gtk/gtkcolumnviewcolumn.h>
|
||||
#include <gtk/gtkcolumnviewsorter.h>
|
||||
#include <gtk/deprecated/gtkcombobox.h>
|
||||
#include <gtk/deprecated/gtkcomboboxtext.h>
|
||||
#include <gtk/gtkchoice.h>
|
||||
#include <gtk/gtkconstraintlayout.h>
|
||||
#include <gtk/gtkconstraint.h>
|
||||
#include <gtk/gtkcssprovider.h>
|
||||
@@ -124,6 +128,7 @@
|
||||
#include <gtk/gtkfilechooserdialog.h>
|
||||
#include <gtk/gtkfilechoosernative.h>
|
||||
#include <gtk/gtkfilechooserwidget.h>
|
||||
#include <gtk/gtkfiledialog.h>
|
||||
#include <gtk/gtkfilefilter.h>
|
||||
#include <gtk/gtkfilter.h>
|
||||
#include <gtk/gtkfilterlistmodel.h>
|
||||
@@ -134,6 +139,8 @@
|
||||
#include <gtk/gtkfontchooser.h>
|
||||
#include <gtk/gtkfontchooserdialog.h>
|
||||
#include <gtk/gtkfontchooserwidget.h>
|
||||
#include <gtk/gtkfontdialog.h>
|
||||
#include <gtk/gtkfontdialogbutton.h>
|
||||
#include <gtk/gtkframe.h>
|
||||
#include <gtk/gtkgesture.h>
|
||||
#include <gtk/gtkgestureclick.h>
|
||||
@@ -157,6 +164,7 @@
|
||||
#include <gtk/gtkimcontextsimple.h>
|
||||
#include <gtk/gtkimmulticontext.h>
|
||||
#include <gtk/gtkinfobar.h>
|
||||
#include <gtk/gtkinfodialog.h>
|
||||
#include <gtk/gtkinscription.h>
|
||||
#include <gtk/gtklabel.h>
|
||||
#include <gtk/gtklayoutmanager.h>
|
||||
|
@@ -27,6 +27,8 @@
|
||||
#include "gtkmarshalers.h"
|
||||
#include "gtkwidgetprivate.h"
|
||||
#include "gsettings-mapping.h"
|
||||
#include "gtkdebug.h"
|
||||
#include "gtkprivate.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@@ -846,9 +848,15 @@ gtk_action_muxer_activate_action (GtkActionMuxer *muxer,
|
||||
if (!_gtk_bitmask_get (muxer->widget_actions_disabled, position))
|
||||
{
|
||||
if (action->activate)
|
||||
action->activate (muxer->widget, action->name, parameter);
|
||||
{
|
||||
GTK_DEBUG (ACTIONS, "%s: activate action", action->name);
|
||||
action->activate (muxer->widget, action->name, parameter);
|
||||
}
|
||||
else if (action->pspec)
|
||||
prop_action_activate (muxer->widget, action, parameter);
|
||||
{
|
||||
GTK_DEBUG (ACTIONS, "%s: activate prop action", action->pspec->name);
|
||||
prop_action_activate (muxer->widget, action, parameter);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
@@ -225,6 +225,7 @@
|
||||
#include "gtkicontheme.h"
|
||||
#include "gtkiconthemeprivate.h"
|
||||
#include "gtkdebug.h"
|
||||
#include "gtkstringlist.h"
|
||||
|
||||
|
||||
static void gtk_builder_finalize (GObject *object);
|
||||
@@ -551,6 +552,19 @@ gtk_builder_get_parameters (GtkBuilder *builder,
|
||||
|
||||
if (G_PARAM_SPEC_VALUE_TYPE (prop->pspec) == GTK_TYPE_EXPRESSION)
|
||||
gtk_value_set_expression (&property_value, prop->value);
|
||||
else if (G_PARAM_SPEC_VALUE_TYPE (prop->pspec) == G_TYPE_STRV)
|
||||
{
|
||||
GStrvBuilder *strv = g_strv_builder_new ();
|
||||
|
||||
for (guint j = 0; j < g_list_model_get_n_items (G_LIST_MODEL (prop->value)); j++)
|
||||
{
|
||||
GtkStringObject *s = g_list_model_get_item (G_LIST_MODEL (prop->value), j);
|
||||
g_strv_builder_add (strv, gtk_string_object_get_string (s));
|
||||
g_object_unref (s);
|
||||
}
|
||||
|
||||
g_value_set_boxed (&property_value, g_strv_builder_end (strv));
|
||||
}
|
||||
else
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
@@ -1039,6 +1039,10 @@ free_property_info (PropertyInfo *info)
|
||||
{
|
||||
if (G_PARAM_SPEC_VALUE_TYPE (info->pspec) == GTK_TYPE_EXPRESSION)
|
||||
gtk_expression_unref (info->value);
|
||||
else if (G_PARAM_SPEC_VALUE_TYPE (info->pspec) == G_TYPE_STRV)
|
||||
{
|
||||
/* info->value is in the hash table of objects */
|
||||
}
|
||||
else
|
||||
g_assert_not_reached();
|
||||
}
|
||||
@@ -1723,8 +1727,11 @@ parse_custom (GtkBuildableParseContext *context,
|
||||
object = ((ObjectInfo*)child_info->parent)->object;
|
||||
child = child_info->object;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
else if (parent_info->tag_type == TAG_PROPERTY)
|
||||
{
|
||||
g_print ("custom markup in <property>\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!gtk_buildable_custom_tag_start (GTK_BUILDABLE (object),
|
||||
data->builder,
|
||||
@@ -1947,7 +1954,10 @@ end_element (GtkBuildableParseContext *context,
|
||||
if (child_info)
|
||||
child_info->object = object_info->object;
|
||||
if (prop_info)
|
||||
g_string_assign (prop_info->text, object_info->id);
|
||||
{
|
||||
g_string_assign (prop_info->text, object_info->id);
|
||||
prop_info->value = object_info->object;
|
||||
}
|
||||
|
||||
if (GTK_IS_BUILDABLE (object_info->object) &&
|
||||
GTK_BUILDABLE_GET_IFACE (object_info->object)->parser_finished)
|
||||
@@ -2074,7 +2084,7 @@ end_element (GtkBuildableParseContext *context,
|
||||
g_set_error (error,
|
||||
GTK_BUILDER_ERROR,
|
||||
GTK_BUILDER_ERROR_UNHANDLED_TAG,
|
||||
"Unhandled tag: <%s>", element_name);
|
||||
"Unhandled end tag: </%s>", element_name);
|
||||
_gtk_builder_prefix_error (data->builder, context, error);
|
||||
}
|
||||
}
|
||||
|
93
gtk/gtkchoice.c
Normal file
93
gtk/gtkchoice.c
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* GTK - The GIMP Toolkit
|
||||
* Copyright (C) 2022 Red Hat, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This Library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This Library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkchoice.h"
|
||||
|
||||
struct _GtkChoice
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
char *label;
|
||||
char **options;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GtkChoice, gtk_choice, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
gtk_choice_init (GtkChoice *self)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_choice_finalize (GObject *object)
|
||||
{
|
||||
GtkChoice *self = GTK_CHOICE (object);
|
||||
|
||||
g_free (self->label);
|
||||
g_strfreev (self->options);
|
||||
|
||||
G_OBJECT_CLASS (gtk_choice_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_choice_class_init (GtkChoiceClass *class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
|
||||
object_class->finalize = gtk_choice_finalize;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Public API */
|
||||
|
||||
GtkChoice *
|
||||
gtk_choice_new (const char *label,
|
||||
const char * const *options)
|
||||
{
|
||||
GtkChoice *self;
|
||||
|
||||
self = g_object_new (GTK_TYPE_CHOICE, NULL);
|
||||
|
||||
self->label = g_strdup (label);
|
||||
self->options = g_strdupv ((char **)options);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
const char *
|
||||
gtk_choice_get_label (GtkChoice *choice)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_CHOICE (choice), NULL);
|
||||
|
||||
return choice->label;
|
||||
}
|
||||
|
||||
const char * const *
|
||||
gtk_choice_get_options (GtkChoice *choice)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_CHOICE (choice), NULL);
|
||||
|
||||
return (const char * const *)choice->options;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* vim:set foldmethod=marker expandtab: */
|
45
gtk/gtkchoice.h
Normal file
45
gtk/gtkchoice.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/* GTK - The GIMP Toolkit
|
||||
*
|
||||
* Copyright (C) 2022 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gtk/gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_CHOICE (gtk_choice_get_type ())
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
G_DECLARE_FINAL_TYPE (GtkChoice, gtk_choice, GTK, CHOICE, GObject)
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
GtkChoice * gtk_choice_new (const char *label,
|
||||
const char * const *options);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
const char * gtk_choice_get_label (GtkChoice *choice);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
const char * const *
|
||||
gtk_choice_get_options (GtkChoice *choice);
|
||||
|
||||
G_END_DECLS
|
475
gtk/gtkcolordialog.c
Normal file
475
gtk/gtkcolordialog.c
Normal file
@@ -0,0 +1,475 @@
|
||||
/*
|
||||
* GTK - The GIMP Toolkit
|
||||
* Copyright (C) 2022 Red Hat, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This Library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This Library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkcolordialog.h"
|
||||
|
||||
#include "gtkcolorchooserdialog.h"
|
||||
#include "gtkcolorchooser.h"
|
||||
#include "gtkbutton.h"
|
||||
#include <glib/gi18n-lib.h>
|
||||
|
||||
/**
|
||||
* GtkColorDialog:
|
||||
*
|
||||
* A `GtkColorDialog` object collects the arguments that
|
||||
* are needed to present a color chooser dialog to the
|
||||
* user, such as a title for the dialog and whether it
|
||||
* should be modal.
|
||||
*
|
||||
* The dialog is shown with the [function@Gtk.ColorDialog.choose_rgba]
|
||||
* function. This API follows the GIO async pattern, and the
|
||||
* result can be obtained by calling
|
||||
* [function@Gtk.ColorDialog.choose_rgba_finish].
|
||||
*
|
||||
* See [class@Gtk.ColorDialogButton] for a convenient control
|
||||
* that uses `GtkColorDialog` and presents the results.
|
||||
*
|
||||
* `GtkColorDialog was added in GTK 4.10.
|
||||
*/
|
||||
/* {{{ GObject implementation */
|
||||
|
||||
struct _GtkColorDialog
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
char *title;
|
||||
|
||||
unsigned int modal : 1;
|
||||
unsigned int with_alpha : 1;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_TITLE = 1,
|
||||
PROP_MODAL,
|
||||
PROP_WITH_ALPHA,
|
||||
|
||||
NUM_PROPERTIES
|
||||
};
|
||||
|
||||
static GParamSpec *properties[NUM_PROPERTIES];
|
||||
|
||||
G_DEFINE_TYPE (GtkColorDialog, gtk_color_dialog, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
gtk_color_dialog_init (GtkColorDialog *self)
|
||||
{
|
||||
self->title = g_strdup (_("Pick a Color"));
|
||||
self->modal = TRUE;
|
||||
self->with_alpha = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_color_dialog_finalize (GObject *object)
|
||||
{
|
||||
GtkColorDialog *self = GTK_COLOR_DIALOG (object);
|
||||
|
||||
g_free (self->title);
|
||||
|
||||
G_OBJECT_CLASS (gtk_color_dialog_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_color_dialog_get_property (GObject *object,
|
||||
unsigned int property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkColorDialog *self = GTK_COLOR_DIALOG (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_TITLE:
|
||||
g_value_set_string (value, self->title);
|
||||
break;
|
||||
|
||||
case PROP_MODAL:
|
||||
g_value_set_boolean (value, self->modal);
|
||||
break;
|
||||
|
||||
case PROP_WITH_ALPHA:
|
||||
g_value_set_boolean (value, self->with_alpha);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_color_dialog_set_property (GObject *object,
|
||||
unsigned int prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkColorDialog *self = GTK_COLOR_DIALOG (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_TITLE:
|
||||
gtk_color_dialog_set_title (self, g_value_get_string (value));
|
||||
break;
|
||||
|
||||
case PROP_MODAL:
|
||||
gtk_color_dialog_set_modal (self, g_value_get_boolean (value));
|
||||
break;
|
||||
|
||||
case PROP_WITH_ALPHA:
|
||||
gtk_color_dialog_set_with_alpha (self, g_value_get_boolean (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_color_dialog_class_init (GtkColorDialogClass *class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
|
||||
object_class->finalize = gtk_color_dialog_finalize;
|
||||
object_class->get_property = gtk_color_dialog_get_property;
|
||||
object_class->set_property = gtk_color_dialog_set_property;
|
||||
|
||||
/**
|
||||
* GtkColorDialog:title: (attributes org.gtk.Property.get=gtk_color_dialog_get_title org.gtk.Property.set=gtk_color_dialog_set_title)
|
||||
*
|
||||
* A title that may be shown on the color chooser
|
||||
* dialog that is presented by [function@Gtk.ColorDialog.choose_rgba].
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
properties[PROP_TITLE] =
|
||||
g_param_spec_string ("title", NULL, NULL,
|
||||
NULL,
|
||||
G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS|G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GtkColorDialog:modal: (attributes org.gtk.Property.get=gtk_color_dialog_get_modal org.gtk.Property.set=gtk_color_dialog_set_modal)
|
||||
*
|
||||
* Whether the color chooser dialog is modal.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
properties[PROP_MODAL] =
|
||||
g_param_spec_boolean ("modal", NULL, NULL,
|
||||
TRUE,
|
||||
G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS|G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GtkColorDialog:with-alpha: (attributes org.gtk.Property.get=gtk_color_dialog_get_with_alpha org.gtk.Property.set=gtk_color_dialog_set_with_alpha)
|
||||
*
|
||||
* Whether colors may have alpha (translucency).
|
||||
*
|
||||
* When with-alpha is %FALSE, the color that is selected
|
||||
* will be forced to have alpha == 1.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
properties[PROP_WITH_ALPHA] =
|
||||
g_param_spec_boolean ("with-alpha", NULL, NULL,
|
||||
TRUE,
|
||||
G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS|G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
g_object_class_install_properties (object_class, NUM_PROPERTIES, properties);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Constructor */
|
||||
|
||||
/**
|
||||
* gtk_color_dialog_new:
|
||||
*
|
||||
* Creates a new `GtkColorDialog` object.
|
||||
*
|
||||
* Returns: the new `GtkColorDialog`
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
GtkColorDialog *
|
||||
gtk_color_dialog_new (void)
|
||||
{
|
||||
return g_object_new (GTK_TYPE_COLOR_DIALOG, NULL);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Getters and setters */
|
||||
|
||||
/**
|
||||
* gtk_color_dialog_get_title:
|
||||
* @self: a `GtkColorDialog`
|
||||
*
|
||||
* Returns the title that will be shown on the
|
||||
* color chooser dialog.
|
||||
*
|
||||
* Returns: the title
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
const char *
|
||||
gtk_color_dialog_get_title (GtkColorDialog *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_COLOR_DIALOG (self), NULL);
|
||||
|
||||
return self->title;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_color_dialog_set_title:
|
||||
* @self: a `GtkColorDialog`
|
||||
* @title: the new title
|
||||
*
|
||||
* Sets the title that will be shown on the
|
||||
* color chooser dialog.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
void
|
||||
gtk_color_dialog_set_title (GtkColorDialog *self,
|
||||
const char *title)
|
||||
{
|
||||
char *new_title;
|
||||
|
||||
g_return_if_fail (GTK_IS_COLOR_DIALOG (self));
|
||||
g_return_if_fail (title != NULL);
|
||||
|
||||
if (g_str_equal (self->title, title))
|
||||
return;
|
||||
|
||||
new_title = g_strdup (title);
|
||||
g_free (self->title);
|
||||
self->title = new_title;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_TITLE]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_color_dialog_get_modal:
|
||||
* @self: a `GtkColorDialog`
|
||||
*
|
||||
* Returns whether the color chooser dialog
|
||||
* blocks interaction with the parent window
|
||||
* while it is presented.
|
||||
*
|
||||
* Returns: `TRUE` if the color chooser dialog is modal
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
gboolean
|
||||
gtk_color_dialog_get_modal (GtkColorDialog *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_COLOR_DIALOG (self), TRUE);
|
||||
|
||||
return self->modal;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_color_dialog_set_modal:
|
||||
* @self: a `GtkColorDialog`
|
||||
* @modal: the new value
|
||||
*
|
||||
* Sets whether the color chooser dialog
|
||||
* blocks interaction with the parent window
|
||||
* while it is presented.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
void
|
||||
gtk_color_dialog_set_modal (GtkColorDialog *self,
|
||||
gboolean modal)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_COLOR_DIALOG (self));
|
||||
|
||||
if (self->modal == modal)
|
||||
return;
|
||||
|
||||
self->modal = modal;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_MODAL]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_color_dialog_get_with_alpha:
|
||||
* @self: a `GtkColorDialog`
|
||||
*
|
||||
* Returns whether colors may have alpha.
|
||||
*
|
||||
* Returns: `TRUE` if colors may have alpha
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
gboolean
|
||||
gtk_color_dialog_get_with_alpha (GtkColorDialog *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_COLOR_DIALOG (self), TRUE);
|
||||
|
||||
return self->with_alpha;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_color_dialog_set_with_alpha:
|
||||
* @self: a `GtkColorDialog`
|
||||
* @with_alpha: the new value
|
||||
*
|
||||
* Sets whether colors may have alpha.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
void
|
||||
gtk_color_dialog_set_with_alpha (GtkColorDialog *self,
|
||||
gboolean with_alpha)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_COLOR_DIALOG (self));
|
||||
|
||||
if (self->with_alpha == with_alpha)
|
||||
return;
|
||||
|
||||
self->with_alpha = with_alpha;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_WITH_ALPHA]);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Async API */
|
||||
|
||||
static void response_cb (GTask *task,
|
||||
int response);
|
||||
|
||||
static void
|
||||
cancelled_cb (GCancellable *cancellable,
|
||||
GTask *task)
|
||||
{
|
||||
response_cb (task, GTK_RESPONSE_CANCEL);
|
||||
}
|
||||
|
||||
static void
|
||||
response_cb (GTask *task,
|
||||
int response)
|
||||
{
|
||||
GCancellable *cancellable;
|
||||
|
||||
cancellable = g_task_get_cancellable (task);
|
||||
|
||||
if (cancellable)
|
||||
g_signal_handlers_disconnect_by_func (cancellable, cancelled_cb, task);
|
||||
|
||||
if (response == GTK_RESPONSE_OK)
|
||||
{
|
||||
GtkColorChooserDialog *window;
|
||||
GdkRGBA color;
|
||||
|
||||
window = GTK_COLOR_CHOOSER_DIALOG (g_task_get_task_data (task));
|
||||
gtk_color_chooser_get_rgba (GTK_COLOR_CHOOSER (window), &color);
|
||||
g_task_return_pointer (task, &color, NULL);
|
||||
}
|
||||
else
|
||||
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_CANCELLED, "Cancelled");
|
||||
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_color_dialog_choose_rgba:
|
||||
* @self: a `GtkColorDialog`
|
||||
* @parent: (nullable): the parent `GtkWindow`
|
||||
* @initial_color: (nullable): the color to select initially
|
||||
* @cancellable: (nullable): a `GCancellable` to cancel the operation
|
||||
* @callback: (scope async): a callback to call when the operation is complete
|
||||
* @user_data: (closure callback): data to pass to @callback
|
||||
*
|
||||
* This function initiates a color choice operation by
|
||||
* presenting a color chooser dialog to the user.
|
||||
*
|
||||
* The @callback will be called when the dialog is dismissed.
|
||||
* It should call [function@Gtk.ColorDialog.choose_rgba_finish]
|
||||
* to obtain the result.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
void
|
||||
gtk_color_dialog_choose_rgba (GtkColorDialog *self,
|
||||
GtkWindow *parent,
|
||||
const GdkRGBA *initial_color,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkWidget *window;
|
||||
GTask *task;
|
||||
|
||||
g_return_if_fail (GTK_IS_COLOR_DIALOG (self));
|
||||
|
||||
window = gtk_color_chooser_dialog_new (self->title, parent);
|
||||
if (initial_color)
|
||||
gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (window), initial_color);
|
||||
gtk_color_chooser_set_use_alpha (GTK_COLOR_CHOOSER (window), self->with_alpha);
|
||||
gtk_window_set_modal (GTK_WINDOW (window), self->modal);
|
||||
|
||||
task = g_task_new (self, cancellable, callback, user_data);
|
||||
g_task_set_source_tag (task, gtk_color_dialog_choose_rgba);
|
||||
g_task_set_task_data (task, window, (GDestroyNotify) gtk_window_destroy);
|
||||
|
||||
if (cancellable)
|
||||
g_signal_connect (cancellable, "cancelled", G_CALLBACK (cancelled_cb), task);
|
||||
g_signal_connect_swapped (window, "response", G_CALLBACK (response_cb), task);
|
||||
|
||||
gtk_window_present (GTK_WINDOW (window));
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_color_dialog_choose_rgba_finish:
|
||||
* @self: a `GtkColorDialog`
|
||||
* @result: a `GAsyncResult`
|
||||
* @color: (out caller-allocates): return location for the color
|
||||
* @error: return location for an error
|
||||
*
|
||||
* Finishes the [function@Gtk.ColorDialog.choose_rgba] call and
|
||||
* returns the resulting color.
|
||||
*
|
||||
* Returns: `TRUE` if a color was selected. Otherwise,
|
||||
* `FALSE` is returned and @error is set
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
gboolean
|
||||
gtk_color_dialog_choose_rgba_finish (GtkColorDialog *self,
|
||||
GAsyncResult *result,
|
||||
GdkRGBA *color,
|
||||
GError **error)
|
||||
{
|
||||
GdkRGBA *ret;
|
||||
|
||||
ret = g_task_propagate_pointer (G_TASK (result), error);
|
||||
if (ret)
|
||||
{
|
||||
*color = *ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* vim:set foldmethod=marker expandtab: */
|
73
gtk/gtkcolordialog.h
Normal file
73
gtk/gtkcolordialog.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/* GTK - The GIMP Toolkit
|
||||
*
|
||||
* Copyright (C) 2022 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gtk/gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <gtk/gtkwindow.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_COLOR_DIALOG (gtk_color_dialog_get_type ())
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
G_DECLARE_FINAL_TYPE (GtkColorDialog, gtk_color_dialog, GTK, COLOR_DIALOG, GObject)
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
GtkColorDialog *gtk_color_dialog_new (void);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
const char * gtk_color_dialog_get_title (GtkColorDialog *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
void gtk_color_dialog_set_title (GtkColorDialog *self,
|
||||
const char *title);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
gboolean gtk_color_dialog_get_modal (GtkColorDialog *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
void gtk_color_dialog_set_modal (GtkColorDialog *self,
|
||||
gboolean modal);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
gboolean gtk_color_dialog_get_with_alpha (GtkColorDialog *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
void gtk_color_dialog_set_with_alpha (GtkColorDialog *self,
|
||||
gboolean with_alpha);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
void gtk_color_dialog_choose_rgba (GtkColorDialog *self,
|
||||
GtkWindow *parent,
|
||||
const GdkRGBA *initial_color,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
gboolean gtk_color_dialog_choose_rgba_finish (GtkColorDialog *self,
|
||||
GAsyncResult *result,
|
||||
GdkRGBA *color,
|
||||
GError **error);
|
||||
|
||||
G_END_DECLS
|
483
gtk/gtkcolordialogbutton.c
Normal file
483
gtk/gtkcolordialogbutton.c
Normal file
@@ -0,0 +1,483 @@
|
||||
/*
|
||||
* GTK - The GIMP Toolkit
|
||||
* Copyright (C) 2022 Red Hat, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This Library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This Library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkcolordialogbutton.h"
|
||||
|
||||
#include "gtkbinlayout.h"
|
||||
#include "gtkbutton.h"
|
||||
#include "gtkcolorswatchprivate.h"
|
||||
#include "gtkdragsource.h"
|
||||
#include "gtkdroptarget.h"
|
||||
#include <glib/gi18n-lib.h>
|
||||
#include "gtkmain.h"
|
||||
#include "gtkmarshalers.h"
|
||||
#include "gtkprivate.h"
|
||||
#include "gtksnapshot.h"
|
||||
#include "gtkwidgetprivate.h"
|
||||
|
||||
|
||||
static gboolean drop (GtkDropTarget *dest,
|
||||
const GValue *value,
|
||||
double x,
|
||||
double y,
|
||||
GtkColorDialogButton *self);
|
||||
static GdkContentProvider *
|
||||
drag_prepare (GtkDragSource *source,
|
||||
double x,
|
||||
double y,
|
||||
GtkColorDialogButton *self);
|
||||
static void button_clicked (GtkColorDialogButton *self);
|
||||
|
||||
/**
|
||||
* GtkColorDialogButton:
|
||||
*
|
||||
* The `GtkColorDialogButton` is a wrapped around a [class@Gtk.ColorDialog]
|
||||
* and allows to open a color chooser dialog to change the color.
|
||||
*
|
||||
* 
|
||||
*
|
||||
* It is suitable widget for selecting a color in a preference dialog.
|
||||
*
|
||||
* # CSS nodes
|
||||
*
|
||||
* ```
|
||||
* colorbutton
|
||||
* ╰── button.color
|
||||
* ╰── [content]
|
||||
* ```
|
||||
*
|
||||
* `GtkColorDialogButton` has a single CSS node with name colorbutton which
|
||||
* contains a button node. To differentiate it from a plain `GtkButton`,
|
||||
* it gets the .color style class.
|
||||
*/
|
||||
|
||||
/* {{{ GObject implementation */
|
||||
|
||||
struct _GtkColorDialogButton
|
||||
{
|
||||
GtkWidget parent_instance;
|
||||
|
||||
GtkWidget *button;
|
||||
GtkWidget *swatch;
|
||||
|
||||
GtkColorDialog *dialog;
|
||||
GdkRGBA color;
|
||||
};
|
||||
|
||||
/* Properties */
|
||||
enum
|
||||
{
|
||||
PROP_DIALOG = 1,
|
||||
PROP_COLOR,
|
||||
NUM_PROPERTIES
|
||||
};
|
||||
|
||||
static GParamSpec *properties[NUM_PROPERTIES];
|
||||
|
||||
G_DEFINE_TYPE (GtkColorDialogButton, gtk_color_dialog_button, GTK_TYPE_WIDGET)
|
||||
|
||||
static void
|
||||
gtk_color_dialog_button_init (GtkColorDialogButton *self)
|
||||
{
|
||||
PangoLayout *layout;
|
||||
PangoRectangle rect;
|
||||
GtkDragSource *source;
|
||||
GtkDropTarget *dest;
|
||||
|
||||
self->button = gtk_button_new ();
|
||||
g_signal_connect_swapped (self->button, "clicked", G_CALLBACK (button_clicked), self);
|
||||
gtk_widget_set_parent (self->button, GTK_WIDGET (self));
|
||||
|
||||
self->swatch = g_object_new (GTK_TYPE_COLOR_SWATCH,
|
||||
"accessible-role", GTK_ACCESSIBLE_ROLE_IMG,
|
||||
"selectable", FALSE,
|
||||
"has-menu", FALSE,
|
||||
"can-drag", FALSE,
|
||||
NULL);
|
||||
gtk_widget_set_can_focus (self->swatch, FALSE);
|
||||
gtk_widget_remove_css_class (self->swatch, "activatable");
|
||||
|
||||
layout = gtk_widget_create_pango_layout (GTK_WIDGET (self), "Black");
|
||||
pango_layout_get_pixel_extents (layout, NULL, &rect);
|
||||
g_object_unref (layout);
|
||||
|
||||
gtk_widget_set_size_request (self->swatch, rect.width, rect.height);
|
||||
|
||||
gtk_button_set_child (GTK_BUTTON (self->button), self->swatch);
|
||||
|
||||
dest = gtk_drop_target_new (GDK_TYPE_RGBA, GDK_ACTION_COPY);
|
||||
g_signal_connect (dest, "drop", G_CALLBACK (drop), self);
|
||||
gtk_widget_add_controller (GTK_WIDGET (self->button), GTK_EVENT_CONTROLLER (dest));
|
||||
|
||||
source = gtk_drag_source_new ();
|
||||
g_signal_connect (source, "prepare", G_CALLBACK (drag_prepare), self);
|
||||
gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (source),
|
||||
GTK_PHASE_CAPTURE);
|
||||
gtk_widget_add_controller (self->button, GTK_EVENT_CONTROLLER (source));
|
||||
gtk_widget_add_css_class (self->button, "color");
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_color_dialog_button_set_property (GObject *object,
|
||||
unsigned int param_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkColorDialogButton *self = GTK_COLOR_DIALOG_BUTTON (object);
|
||||
|
||||
switch (param_id)
|
||||
{
|
||||
case PROP_DIALOG:
|
||||
gtk_color_dialog_button_set_dialog (self, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
case PROP_COLOR:
|
||||
gtk_color_dialog_button_set_color (self, g_value_get_boxed (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_color_dialog_button_get_property (GObject *object,
|
||||
unsigned int param_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkColorDialogButton *self = GTK_COLOR_DIALOG_BUTTON (object);
|
||||
|
||||
switch (param_id)
|
||||
{
|
||||
case PROP_DIALOG:
|
||||
g_value_set_object (value, self->dialog);
|
||||
break;
|
||||
|
||||
case PROP_COLOR:
|
||||
g_value_set_boxed (value, &self->color);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_color_dialog_button_dispose (GObject *object)
|
||||
{
|
||||
GtkColorDialogButton *self = GTK_COLOR_DIALOG_BUTTON (object);
|
||||
|
||||
g_clear_pointer (&self->button, gtk_widget_unparent);
|
||||
|
||||
G_OBJECT_CLASS (gtk_color_dialog_button_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_color_dialog_button_finalize (GObject *object)
|
||||
{
|
||||
GtkColorDialogButton *self = GTK_COLOR_DIALOG_BUTTON (object);
|
||||
|
||||
g_clear_object (&self->dialog);
|
||||
|
||||
G_OBJECT_CLASS (gtk_color_dialog_button_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_color_dialog_button_class_init (GtkColorDialogButtonClass *class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
|
||||
|
||||
object_class->get_property = gtk_color_dialog_button_get_property;
|
||||
object_class->set_property = gtk_color_dialog_button_set_property;
|
||||
object_class->dispose = gtk_color_dialog_button_dispose;
|
||||
object_class->finalize = gtk_color_dialog_button_finalize;
|
||||
|
||||
widget_class->grab_focus = gtk_widget_grab_focus_child;
|
||||
widget_class->focus = gtk_widget_focus_child;
|
||||
|
||||
/**
|
||||
* GtkColorDialogButton:dialog: (attributes org.gtk.Property.get=gtk_color_dialog_button_get_dialog org.gtk.Property.set=gtk_color_dialog_button_set_dialog)
|
||||
*
|
||||
* The `GtkColorDialog` that contains parameters for
|
||||
* the color chooser dialog.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
properties[PROP_DIALOG] =
|
||||
g_param_spec_object ("dialog", NULL, NULL,
|
||||
GTK_TYPE_COLOR_DIALOG,
|
||||
G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS|G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GtkColorDialogButton:color: (attributes org.gtk.Property.get=gtk_color_dialog_button_get_color org.gtk.Property.set=gtk_color_dialog_button_set_color)
|
||||
*
|
||||
* The selected color.
|
||||
*
|
||||
* This property can be set to give the button its initial
|
||||
* color, and it will be updated to reflect the users choice
|
||||
* in the color chooser dialog.
|
||||
*
|
||||
* Listen to `notify::color` to get informed about changes
|
||||
* to the buttons color.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
properties[PROP_COLOR] =
|
||||
g_param_spec_boxed ("color", NULL, NULL,
|
||||
GDK_TYPE_RGBA,
|
||||
G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS|G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
g_object_class_install_properties (object_class, NUM_PROPERTIES, properties);
|
||||
|
||||
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
|
||||
gtk_widget_class_set_css_name (widget_class, "colorbutton");
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Private API, callbacks */
|
||||
|
||||
static guint
|
||||
scale_round (double value,
|
||||
double scale)
|
||||
{
|
||||
value = floor (value * scale + 0.5);
|
||||
value = CLAMP (value, 0, scale);
|
||||
return (guint)value;
|
||||
}
|
||||
|
||||
static char *
|
||||
accessible_color_name (const GdkRGBA *color)
|
||||
{
|
||||
if (color->alpha < 1.0)
|
||||
return g_strdup_printf (_("Red %d%%, Green %d%%, Blue %d%%, Alpha %d%%"),
|
||||
scale_round (color->red, 100),
|
||||
scale_round (color->green, 100),
|
||||
scale_round (color->blue, 100),
|
||||
scale_round (color->alpha, 100));
|
||||
else
|
||||
return g_strdup_printf (_("Red %d%%, Green %d%%, Blue %d%%"),
|
||||
scale_round (color->red, 100),
|
||||
scale_round (color->green, 100),
|
||||
scale_round (color->blue, 100));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
drop (GtkDropTarget *dest,
|
||||
const GValue *value,
|
||||
double x,
|
||||
double y,
|
||||
GtkColorDialogButton *self)
|
||||
{
|
||||
GdkRGBA *color = g_value_get_boxed (value);
|
||||
|
||||
gtk_color_dialog_button_set_color (self, color);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GdkContentProvider *
|
||||
drag_prepare (GtkDragSource *source,
|
||||
double x,
|
||||
double y,
|
||||
GtkColorDialogButton *self)
|
||||
{
|
||||
GdkRGBA color;
|
||||
|
||||
gtk_color_swatch_get_rgba (GTK_COLOR_SWATCH (self->swatch), &color);
|
||||
|
||||
return gdk_content_provider_new_typed (GDK_TYPE_RGBA, &color);
|
||||
}
|
||||
|
||||
static void
|
||||
color_chosen (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer data)
|
||||
{
|
||||
GtkColorDialogButton *self = data;
|
||||
GdkRGBA color;
|
||||
GError *error = NULL;
|
||||
|
||||
if (gtk_color_dialog_choose_rgba_finish (self->dialog, result, &color, &error))
|
||||
{
|
||||
gtk_color_dialog_button_set_color (self, &color);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_print ("%s\n", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
button_clicked (GtkColorDialogButton *self)
|
||||
{
|
||||
GtkRoot *root = gtk_widget_get_root (GTK_WIDGET (self));
|
||||
GtkWindow *parent = NULL;
|
||||
|
||||
if (GTK_IS_WINDOW (root))
|
||||
parent = GTK_WINDOW (root);
|
||||
|
||||
gtk_color_dialog_choose_rgba (self->dialog, parent, &self->color,
|
||||
NULL, color_chosen, self);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Constructor */
|
||||
|
||||
/**
|
||||
* gtk_color_dialog_button_new:
|
||||
* @dialog: (nullable) (transfer full): the `GtkColorDialog` to use
|
||||
*
|
||||
* Creates a new `GtkColorDialogButton` with the
|
||||
* given `GtkColorDialog`.
|
||||
*
|
||||
* You can pass `NULL` to this function and set a `GtkColorDialog`
|
||||
* later. The button will be insensitive until that happens.
|
||||
*
|
||||
* Returns: the new `GtkColorDialogButton`
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
GtkWidget *
|
||||
gtk_color_dialog_button_new (GtkColorDialog *dialog)
|
||||
{
|
||||
GtkWidget *self;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_COLOR_DIALOG (dialog), NULL);
|
||||
|
||||
self = g_object_new (GTK_TYPE_COLOR_DIALOG_BUTTON,
|
||||
"dialog", dialog,
|
||||
NULL);
|
||||
|
||||
g_clear_object (&dialog);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Getters and setters */
|
||||
|
||||
/**
|
||||
* gtk_color_dialog_button_get_dialog:
|
||||
* @self: a `GtkColorDialogButton`
|
||||
*
|
||||
* Returns the `GtkColorDialog` of @self.
|
||||
*
|
||||
* Returns: (transfer none) (nullable): the `GtkColorDialog`
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
GtkColorDialog *
|
||||
gtk_color_dialog_button_get_dialog (GtkColorDialogButton *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_COLOR_DIALOG_BUTTON (self), NULL);
|
||||
|
||||
return self->dialog;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_color_dialog_button_set_dialog:
|
||||
* @self: a `GtkColorDialogButton`
|
||||
* @dialog: the new `GtkColorDialog`
|
||||
*
|
||||
* Sets a `GtkColorDialog` object to use for
|
||||
* creating the color chooser dialog that is
|
||||
* presented when the user clicks the button.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
void
|
||||
gtk_color_dialog_button_set_dialog (GtkColorDialogButton *self,
|
||||
GtkColorDialog *dialog)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_COLOR_DIALOG_BUTTON (self));
|
||||
g_return_if_fail (GTK_IS_COLOR_DIALOG (dialog));
|
||||
|
||||
if (!g_set_object (&self->dialog, dialog))
|
||||
return;
|
||||
|
||||
gtk_widget_set_sensitive (self->button, dialog != NULL);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DIALOG]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_color_dialog_button_get_color:
|
||||
* @self: a `GtkColorDialogButton`
|
||||
*
|
||||
* Returns the color of the button.
|
||||
*
|
||||
* This function is what should be used to obtain
|
||||
* the color that was choosen by the user. To get
|
||||
* informed about changes, listen to "notify::color".
|
||||
*
|
||||
* Returns: the color
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
const GdkRGBA *
|
||||
gtk_color_dialog_button_get_color (GtkColorDialogButton *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_COLOR_DIALOG_BUTTON (self), NULL);
|
||||
|
||||
return &self->color;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_color_dialog_button_set_color:
|
||||
* @self: a `GtkColorDialogButton`
|
||||
* @color: the new color
|
||||
*
|
||||
* Sets the color of the button.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
void
|
||||
gtk_color_dialog_button_set_color (GtkColorDialogButton *self,
|
||||
const GdkRGBA *color)
|
||||
{
|
||||
char *text;
|
||||
|
||||
g_return_if_fail (GTK_IS_COLOR_DIALOG_BUTTON (self));
|
||||
g_return_if_fail (color != NULL);
|
||||
|
||||
if (gdk_rgba_equal (&self->color, color))
|
||||
return;
|
||||
|
||||
self->color = *color;
|
||||
gtk_color_swatch_set_rgba (GTK_COLOR_SWATCH (self->swatch), color);
|
||||
|
||||
text = accessible_color_name (color);
|
||||
gtk_accessible_update_property (GTK_ACCESSIBLE (self->swatch),
|
||||
GTK_ACCESSIBLE_PROPERTY_LABEL, text,
|
||||
-1);
|
||||
g_free (text);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_COLOR]);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* vim:set foldmethod=marker expandtab: */
|
53
gtk/gtkcolordialogbutton.h
Normal file
53
gtk/gtkcolordialogbutton.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* GTK - The GIMP Toolkit
|
||||
* Copyright (C) 2022 Red Hat, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This Library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This Library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gtk/gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gtk/gtkbutton.h>
|
||||
#include <gtk/gtkcolordialog.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_COLOR_DIALOG_BUTTON (gtk_color_dialog_button_get_type ())
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
G_DECLARE_FINAL_TYPE (GtkColorDialogButton, gtk_color_dialog_button, GTK, COLOR_DIALOG_BUTTON, GtkWidget)
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
GtkWidget * gtk_color_dialog_button_new (GtkColorDialog *dialog);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
GtkColorDialog *gtk_color_dialog_button_get_dialog (GtkColorDialogButton *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
void gtk_color_dialog_button_set_dialog (GtkColorDialogButton *self,
|
||||
GtkColorDialog *dialog);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
const GdkRGBA * gtk_color_dialog_button_get_color (GtkColorDialogButton *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
void gtk_color_dialog_button_set_color (GtkColorDialogButton *self,
|
||||
const GdkRGBA *color);
|
||||
|
||||
G_END_DECLS
|
@@ -25,6 +25,7 @@
|
||||
|
||||
#include "gtkcomposetable.h"
|
||||
#include "gtkimcontextsimple.h"
|
||||
#include "gtkprivate.h"
|
||||
|
||||
|
||||
#define GTK_COMPOSE_TABLE_MAGIC "GtkComposeTable"
|
||||
|
@@ -61,7 +61,8 @@ struct _GtkEntryCompletion
|
||||
|
||||
gulong completion_timeout;
|
||||
gulong changed_id;
|
||||
gulong insert_text_id;
|
||||
|
||||
GSignalGroup *insert_text_signal_group;
|
||||
|
||||
int current_selected;
|
||||
|
||||
|
304
gtk/gtkfilechoosercell.c
Normal file
304
gtk/gtkfilechoosercell.c
Normal file
@@ -0,0 +1,304 @@
|
||||
/*
|
||||
* Copyright © 2022 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Matthias Clasen <mclasen@redhat.com>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkfilechoosercellprivate.h"
|
||||
|
||||
#include "gtkprivate.h"
|
||||
#include "gtkbinlayout.h"
|
||||
#include "gtkdragsource.h"
|
||||
#include "gtkgestureclick.h"
|
||||
#include "gtkgesturelongpress.h"
|
||||
#include "gtkicontheme.h"
|
||||
#include "gtklistitem.h"
|
||||
#include "gtkselectionmodel.h"
|
||||
#include "gtkfilechooserutils.h"
|
||||
#include "gtkfilechooserwidget.h"
|
||||
#include "gtkfilechooserwidgetprivate.h"
|
||||
|
||||
struct _GtkFileChooserCell
|
||||
{
|
||||
GtkWidget parent_instance;
|
||||
|
||||
GFileInfo *item;
|
||||
gboolean selected;
|
||||
guint position;
|
||||
|
||||
gboolean show_time;
|
||||
};
|
||||
|
||||
struct _GtkFileChooserCellClass
|
||||
{
|
||||
GtkWidgetClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GtkFileChooserCell, gtk_file_chooser_cell, GTK_TYPE_WIDGET)
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_POSITION = 1,
|
||||
PROP_SELECTED,
|
||||
PROP_ITEM,
|
||||
PROP_SHOW_TIME,
|
||||
};
|
||||
|
||||
#define ICON_SIZE 16
|
||||
|
||||
static void
|
||||
popup_menu (GtkFileChooserCell *self,
|
||||
double x,
|
||||
double y)
|
||||
{
|
||||
GtkWidget *widget = GTK_WIDGET (self);
|
||||
GtkSelectionModel *model;
|
||||
GtkWidget *impl;
|
||||
double xx, yy;
|
||||
|
||||
impl = gtk_widget_get_ancestor (widget, GTK_TYPE_FILE_CHOOSER_WIDGET);
|
||||
|
||||
model = gtk_file_chooser_widget_get_selection_model (GTK_FILE_CHOOSER_WIDGET (impl));
|
||||
gtk_selection_model_select_item (model, self->position, TRUE);
|
||||
|
||||
gtk_widget_translate_coordinates (widget, GTK_WIDGET (impl),
|
||||
x, y, &xx, &yy);
|
||||
|
||||
gtk_widget_activate_action (widget, "item.popup-file-list-menu",
|
||||
"(udd)", self->position, xx, yy);
|
||||
}
|
||||
|
||||
static void
|
||||
file_chooser_cell_clicked (GtkEventController *controller,
|
||||
int n_press,
|
||||
double x,
|
||||
double y)
|
||||
{
|
||||
GtkWidget *widget = gtk_event_controller_get_widget (controller);
|
||||
GtkFileChooserCell *self = GTK_FILE_CHOOSER_CELL (widget);
|
||||
|
||||
gtk_gesture_set_state (GTK_GESTURE (controller), GTK_EVENT_SEQUENCE_CLAIMED);
|
||||
popup_menu (self, x, y);
|
||||
}
|
||||
|
||||
static void
|
||||
file_chooser_cell_long_pressed (GtkEventController *controller,
|
||||
double x,
|
||||
double y)
|
||||
{
|
||||
GtkWidget *widget = gtk_event_controller_get_widget (controller);
|
||||
GtkFileChooserCell *self = GTK_FILE_CHOOSER_CELL (widget);
|
||||
|
||||
gtk_gesture_set_state (GTK_GESTURE (controller), GTK_EVENT_SEQUENCE_CLAIMED);
|
||||
popup_menu (self, x, y);
|
||||
}
|
||||
|
||||
static GdkContentProvider *
|
||||
drag_prepare_cb (GtkDragSource *source,
|
||||
double x,
|
||||
double y,
|
||||
gpointer user_data)
|
||||
{
|
||||
GdkContentProvider *provider;
|
||||
GSList *selection;
|
||||
GtkFileChooserWidget *impl;
|
||||
GtkIconTheme *icon_theme;
|
||||
GIcon *icon;
|
||||
int scale;
|
||||
GtkIconPaintable *paintable;
|
||||
GtkFileChooserCell *self = user_data;
|
||||
|
||||
impl = GTK_FILE_CHOOSER_WIDGET (gtk_widget_get_ancestor (GTK_WIDGET (self),
|
||||
GTK_TYPE_FILE_CHOOSER_WIDGET));
|
||||
|
||||
if (!self->selected)
|
||||
{
|
||||
gtk_selection_model_select_item (gtk_file_chooser_widget_get_selection_model (impl),
|
||||
self->position, TRUE);
|
||||
}
|
||||
|
||||
selection = gtk_file_chooser_widget_get_selected_files (impl);
|
||||
if (!selection)
|
||||
return NULL;
|
||||
|
||||
scale = gtk_widget_get_scale_factor (GTK_WIDGET (self));
|
||||
icon_theme = gtk_icon_theme_get_for_display (gtk_widget_get_display (GTK_WIDGET (self)));
|
||||
|
||||
icon = _gtk_file_info_get_icon (self->item, ICON_SIZE, scale, icon_theme);
|
||||
|
||||
paintable = gtk_icon_theme_lookup_by_gicon (icon_theme,icon, ICON_SIZE, scale, GTK_TEXT_DIR_NONE, 0);
|
||||
|
||||
gtk_drag_source_set_icon (source, GDK_PAINTABLE (paintable), x, y);
|
||||
|
||||
provider = gdk_content_provider_new_typed (GDK_TYPE_FILE_LIST, selection);
|
||||
g_slist_free_full (selection, g_object_unref);
|
||||
g_object_unref (paintable);
|
||||
g_object_unref (icon);
|
||||
|
||||
return provider;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_file_chooser_cell_realize (GtkWidget *widget)
|
||||
{
|
||||
GtkFileChooserCell *self = GTK_FILE_CHOOSER_CELL (widget);
|
||||
GtkFileChooserWidget *impl;
|
||||
|
||||
impl = GTK_FILE_CHOOSER_WIDGET (gtk_widget_get_ancestor (GTK_WIDGET (self),
|
||||
GTK_TYPE_FILE_CHOOSER_WIDGET));
|
||||
|
||||
g_object_bind_property (impl, "show-time", self, "show-time", G_BINDING_SYNC_CREATE);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_file_chooser_cell_init (GtkFileChooserCell *self)
|
||||
{
|
||||
GtkGesture *gesture;
|
||||
GtkDragSource *drag_source;
|
||||
|
||||
gesture = gtk_gesture_click_new ();
|
||||
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (gesture), GDK_BUTTON_SECONDARY);
|
||||
g_signal_connect (gesture, "pressed", G_CALLBACK (file_chooser_cell_clicked), NULL);
|
||||
gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (gesture));
|
||||
|
||||
gesture = gtk_gesture_long_press_new ();
|
||||
gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (gesture), TRUE);
|
||||
g_signal_connect (gesture, "pressed", G_CALLBACK (file_chooser_cell_long_pressed), NULL);
|
||||
|
||||
drag_source = gtk_drag_source_new ();
|
||||
gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (drag_source));
|
||||
g_signal_connect (drag_source, "prepare", G_CALLBACK (drag_prepare_cb), self);
|
||||
|
||||
g_signal_connect (self, "realize", G_CALLBACK (gtk_file_chooser_cell_realize), NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_file_chooser_cell_dispose (GObject *object)
|
||||
{
|
||||
GtkWidget *child;
|
||||
|
||||
while ((child = gtk_widget_get_first_child (GTK_WIDGET (object))))
|
||||
gtk_widget_unparent (child);
|
||||
|
||||
G_OBJECT_CLASS (gtk_file_chooser_cell_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_file_chooser_cell_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkFileChooserCell *self = GTK_FILE_CHOOSER_CELL (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_POSITION:
|
||||
self->position = g_value_get_uint (value);
|
||||
break;
|
||||
|
||||
case PROP_SELECTED:
|
||||
self->selected = g_value_get_boolean (value);
|
||||
break;
|
||||
|
||||
case PROP_ITEM:
|
||||
self->item = g_value_get_object (value);
|
||||
break;
|
||||
|
||||
case PROP_SHOW_TIME:
|
||||
self->show_time = g_value_get_boolean (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_file_chooser_cell_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkFileChooserCell *self = GTK_FILE_CHOOSER_CELL (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_POSITION:
|
||||
g_value_set_uint (value, self->position);
|
||||
break;
|
||||
|
||||
case PROP_SELECTED:
|
||||
g_value_set_boolean (value, self->selected);
|
||||
break;
|
||||
|
||||
case PROP_ITEM:
|
||||
g_value_set_object (value, self->item);
|
||||
break;
|
||||
|
||||
case PROP_SHOW_TIME:
|
||||
g_value_set_boolean (value, self->show_time);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gtk_file_chooser_cell_class_init (GtkFileChooserCellClass *klass)
|
||||
{
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->dispose = gtk_file_chooser_cell_dispose;
|
||||
object_class->set_property = gtk_file_chooser_cell_set_property;
|
||||
object_class->get_property = gtk_file_chooser_cell_get_property;
|
||||
|
||||
g_object_class_install_property (object_class, PROP_POSITION,
|
||||
g_param_spec_uint ("position", NULL, NULL,
|
||||
0, G_MAXUINT, 0,
|
||||
GTK_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_SELECTED,
|
||||
g_param_spec_boolean ("selected", NULL, NULL,
|
||||
FALSE,
|
||||
GTK_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_ITEM,
|
||||
g_param_spec_object ("item", NULL, NULL,
|
||||
G_TYPE_FILE_INFO,
|
||||
GTK_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_SHOW_TIME,
|
||||
g_param_spec_boolean ("show-time", NULL, NULL,
|
||||
FALSE,
|
||||
GTK_PARAM_READWRITE));
|
||||
|
||||
gtk_widget_class_set_css_name (widget_class, I_("filelistcell"));
|
||||
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
|
||||
}
|
||||
|
||||
GtkFileChooserCell *
|
||||
gtk_file_chooser_cell_new (void)
|
||||
{
|
||||
return g_object_new (GTK_TYPE_FILE_CHOOSER_CELL, NULL);
|
||||
}
|
37
gtk/gtkfilechoosercellprivate.h
Normal file
37
gtk/gtkfilechoosercellprivate.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright © 2022 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Matthias Clasen
|
||||
*/
|
||||
|
||||
#ifndef __GTK_FILE_CHOOSER_CELL_PRIVATE_H__
|
||||
#define __GTK_FILE_CHOOSER_CELL_PRIVATE_H__
|
||||
|
||||
#include <gtk/gtkwidget.h>
|
||||
#include <gtk/gtkexpression.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_FILE_CHOOSER_CELL (gtk_file_chooser_cell_get_type ())
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
G_DECLARE_FINAL_TYPE (GtkFileChooserCell, gtk_file_chooser_cell, GTK, FILE_CHOOSER_CELL, GtkWidget)
|
||||
|
||||
GtkFileChooserCell * gtk_file_chooser_cell_new (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_FILE_CHOOSER_CELL_PRIVATE_H__ */
|
@@ -60,7 +60,8 @@ struct _GtkFileChooserEntry
|
||||
char *dir_part;
|
||||
char *file_part;
|
||||
|
||||
GtkTreeModel *completion_store;
|
||||
GtkTreeStore *completion_store;
|
||||
GtkFileSystemModel *model;
|
||||
GtkFileFilter *current_filter;
|
||||
|
||||
guint current_folder_loaded : 1;
|
||||
@@ -71,6 +72,7 @@ struct _GtkFileChooserEntry
|
||||
|
||||
enum
|
||||
{
|
||||
FILE_INFO_COLUMN,
|
||||
DISPLAY_NAME_COLUMN,
|
||||
FULL_PATH_COLUMN,
|
||||
N_COLUMNS
|
||||
@@ -197,20 +199,21 @@ match_func (GtkEntryCompletion *compl,
|
||||
* current file filter (e.g. just jpg files) here. */
|
||||
if (chooser_entry->current_filter != NULL)
|
||||
{
|
||||
GFile *file;
|
||||
GFileInfo *info;
|
||||
|
||||
file = _gtk_file_system_model_get_file (GTK_FILE_SYSTEM_MODEL (chooser_entry->completion_store),
|
||||
iter);
|
||||
info = _gtk_file_system_model_get_info (GTK_FILE_SYSTEM_MODEL (chooser_entry->completion_store),
|
||||
iter);
|
||||
gtk_tree_model_get (GTK_TREE_MODEL (chooser_entry->completion_store),
|
||||
iter,
|
||||
FILE_INFO_COLUMN, &info,
|
||||
-1);
|
||||
|
||||
g_assert (info != NULL);
|
||||
g_object_unref (info);
|
||||
|
||||
/* We always allow navigating into subfolders, so don't ever filter directories */
|
||||
if (g_file_info_get_file_type (info) != G_FILE_TYPE_REGULAR)
|
||||
return TRUE;
|
||||
|
||||
if (!g_file_info_has_attribute (info, "standard::file"))
|
||||
g_file_info_set_attribute_object (info, "standard::file", G_OBJECT (file));
|
||||
g_assert (g_file_info_has_attribute (info, "standard::file"));
|
||||
|
||||
return gtk_filter_match (GTK_FILTER (chooser_entry->current_filter), info);
|
||||
}
|
||||
@@ -428,7 +431,7 @@ explicitly_complete (GtkFileChooserEntry *chooser_entry)
|
||||
{
|
||||
chooser_entry->complete_on_load = FALSE;
|
||||
|
||||
if (chooser_entry->completion_store)
|
||||
if (chooser_entry->model)
|
||||
{
|
||||
char *completion, *text;
|
||||
gsize completion_len, text_len;
|
||||
@@ -539,77 +542,93 @@ update_inline_completion (GtkFileChooserEntry *chooser_entry)
|
||||
static void
|
||||
discard_completion_store (GtkFileChooserEntry *chooser_entry)
|
||||
{
|
||||
if (!chooser_entry->completion_store)
|
||||
if (!chooser_entry->model)
|
||||
return;
|
||||
|
||||
g_assert (chooser_entry->completion_store != NULL);
|
||||
|
||||
gtk_entry_completion_set_model (gtk_entry_get_completion (GTK_ENTRY (chooser_entry)), NULL);
|
||||
update_inline_completion (chooser_entry);
|
||||
g_object_unref (chooser_entry->completion_store);
|
||||
chooser_entry->completion_store = NULL;
|
||||
g_clear_object (&chooser_entry->completion_store);
|
||||
g_clear_object (&chooser_entry->model);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
completion_store_set (GtkFileSystemModel *model,
|
||||
GFile *file,
|
||||
GFileInfo *info,
|
||||
int column,
|
||||
GValue *value,
|
||||
gpointer data)
|
||||
static void
|
||||
model_items_changed_cb (GListModel *model,
|
||||
guint position,
|
||||
guint removed,
|
||||
guint added,
|
||||
GtkFileChooserEntry *self)
|
||||
{
|
||||
GtkFileChooserEntry *chooser_entry = data;
|
||||
|
||||
const char *prefix = "";
|
||||
const char *suffix = "";
|
||||
|
||||
switch (column)
|
||||
if (removed > 0)
|
||||
{
|
||||
case FULL_PATH_COLUMN:
|
||||
prefix = chooser_entry->dir_part;
|
||||
G_GNUC_FALLTHROUGH;
|
||||
case DISPLAY_NAME_COLUMN:
|
||||
GtkTreeIter iter;
|
||||
|
||||
if (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (self->completion_store),
|
||||
&iter,
|
||||
NULL,
|
||||
position))
|
||||
{
|
||||
while (removed--)
|
||||
gtk_tree_store_remove (self->completion_store, &iter);
|
||||
}
|
||||
}
|
||||
|
||||
while (added-- > 0)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
GFileInfo *info;
|
||||
const char *suffix = NULL;
|
||||
char *full_path;
|
||||
char *display_name;
|
||||
|
||||
info = g_list_model_get_item (model, position);
|
||||
|
||||
if (_gtk_file_info_consider_as_directory (info))
|
||||
suffix = G_DIR_SEPARATOR_S;
|
||||
|
||||
g_value_take_string (value,
|
||||
g_strconcat (prefix,
|
||||
g_file_info_get_display_name (info),
|
||||
suffix,
|
||||
NULL));
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
display_name = g_strconcat (g_file_info_get_display_name (info), suffix, NULL);
|
||||
full_path = g_strconcat (self->dir_part, display_name, NULL);
|
||||
|
||||
return TRUE;
|
||||
gtk_tree_store_insert_with_values (self->completion_store,
|
||||
&iter, NULL,
|
||||
position,
|
||||
FILE_INFO_COLUMN, info,
|
||||
FULL_PATH_COLUMN, full_path,
|
||||
DISPLAY_NAME_COLUMN, display_name,
|
||||
-1);
|
||||
|
||||
g_clear_object (&info);
|
||||
|
||||
position++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fills the completion store from the contents of the current folder */
|
||||
static void
|
||||
populate_completion_store (GtkFileChooserEntry *chooser_entry)
|
||||
{
|
||||
chooser_entry->completion_store = GTK_TREE_MODEL (
|
||||
chooser_entry->completion_store = gtk_tree_store_new (N_COLUMNS,
|
||||
G_TYPE_FILE_INFO,
|
||||
G_TYPE_STRING,
|
||||
G_TYPE_STRING);
|
||||
|
||||
chooser_entry->model =
|
||||
_gtk_file_system_model_new_for_directory (chooser_entry->current_folder_file,
|
||||
"standard::name,standard::display-name,standard::type,"
|
||||
"standard::content-type",
|
||||
completion_store_set,
|
||||
chooser_entry,
|
||||
N_COLUMNS,
|
||||
G_TYPE_STRING,
|
||||
G_TYPE_STRING));
|
||||
g_signal_connect (chooser_entry->completion_store, "finished-loading",
|
||||
"standard::content-type");
|
||||
g_signal_connect (chooser_entry->model, "items-changed",
|
||||
G_CALLBACK (model_items_changed_cb), chooser_entry);
|
||||
g_signal_connect (chooser_entry->model, "finished-loading",
|
||||
G_CALLBACK (finished_loading_cb), chooser_entry);
|
||||
|
||||
_gtk_file_system_model_set_filter_folders (GTK_FILE_SYSTEM_MODEL (chooser_entry->completion_store),
|
||||
TRUE);
|
||||
_gtk_file_system_model_set_show_files (GTK_FILE_SYSTEM_MODEL (chooser_entry->completion_store),
|
||||
_gtk_file_system_model_set_filter_folders (chooser_entry->model, TRUE);
|
||||
_gtk_file_system_model_set_show_files (chooser_entry->model,
|
||||
chooser_entry->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
|
||||
chooser_entry->action == GTK_FILE_CHOOSER_ACTION_SAVE);
|
||||
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (chooser_entry->completion_store),
|
||||
DISPLAY_NAME_COLUMN, GTK_SORT_ASCENDING);
|
||||
|
||||
gtk_entry_completion_set_model (gtk_entry_get_completion (GTK_ENTRY (chooser_entry)),
|
||||
chooser_entry->completion_store);
|
||||
GTK_TREE_MODEL (chooser_entry->completion_store));
|
||||
}
|
||||
|
||||
/* Callback when the current folder finishes loading */
|
||||
@@ -637,7 +656,7 @@ finished_loading_cb (GtkFileSystemModel *model,
|
||||
completion = gtk_entry_get_completion (GTK_ENTRY (chooser_entry));
|
||||
update_inline_completion (chooser_entry);
|
||||
|
||||
if (gtk_widget_has_focus (GTK_WIDGET (chooser_entry)))
|
||||
if (gtk_widget_has_focus (GTK_WIDGET (gtk_entry_get_text_widget (GTK_ENTRY (chooser_entry)))))
|
||||
{
|
||||
gtk_entry_completion_complete (completion);
|
||||
gtk_entry_completion_insert_prefix (completion);
|
||||
@@ -658,11 +677,7 @@ set_completion_folder (GtkFileChooserEntry *chooser_entry,
|
||||
return;
|
||||
}
|
||||
|
||||
if (chooser_entry->current_folder_file)
|
||||
{
|
||||
g_object_unref (chooser_entry->current_folder_file);
|
||||
chooser_entry->current_folder_file = NULL;
|
||||
}
|
||||
g_clear_object (&chooser_entry->current_folder_file);
|
||||
|
||||
g_free (chooser_entry->dir_part);
|
||||
chooser_entry->dir_part = g_strdup (dir_part);
|
||||
@@ -710,7 +725,7 @@ refresh_current_folder_and_file_part (GtkFileChooserEntry *chooser_entry)
|
||||
|
||||
g_free (dir_part);
|
||||
|
||||
if (chooser_entry->completion_store &&
|
||||
if (chooser_entry->model &&
|
||||
(g_strcmp0 (old_file_part, chooser_entry->file_part) != 0))
|
||||
{
|
||||
GtkFileFilter *filter;
|
||||
@@ -720,8 +735,7 @@ refresh_current_folder_and_file_part (GtkFileChooserEntry *chooser_entry)
|
||||
pattern = g_strconcat (chooser_entry->file_part, "*", NULL);
|
||||
gtk_file_filter_add_pattern (filter, pattern);
|
||||
|
||||
_gtk_file_system_model_set_filter (GTK_FILE_SYSTEM_MODEL (chooser_entry->completion_store),
|
||||
filter);
|
||||
_gtk_file_system_model_set_filter (chooser_entry->model, filter);
|
||||
|
||||
g_free (pattern);
|
||||
g_object_unref (filter);
|
||||
@@ -940,8 +954,8 @@ _gtk_file_chooser_entry_set_action (GtkFileChooserEntry *chooser_entry,
|
||||
break;
|
||||
}
|
||||
|
||||
if (chooser_entry->completion_store)
|
||||
_gtk_file_system_model_set_show_files (GTK_FILE_SYSTEM_MODEL (chooser_entry->completion_store),
|
||||
if (chooser_entry->model)
|
||||
_gtk_file_system_model_set_show_files (chooser_entry->model,
|
||||
action == GTK_FILE_CHOOSER_ACTION_OPEN ||
|
||||
action == GTK_FILE_CHOOSER_ACTION_SAVE);
|
||||
|
||||
@@ -971,17 +985,14 @@ gboolean
|
||||
_gtk_file_chooser_entry_get_is_folder (GtkFileChooserEntry *chooser_entry,
|
||||
GFile *file)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
GFileInfo *info;
|
||||
|
||||
if (chooser_entry->completion_store == NULL ||
|
||||
!_gtk_file_system_model_get_iter_for_file (GTK_FILE_SYSTEM_MODEL (chooser_entry->completion_store),
|
||||
&iter,
|
||||
file))
|
||||
if (chooser_entry->model == NULL)
|
||||
return FALSE;
|
||||
|
||||
info = _gtk_file_system_model_get_info (GTK_FILE_SYSTEM_MODEL (chooser_entry->completion_store),
|
||||
&iter);
|
||||
info = _gtk_file_system_model_get_info_for_file (chooser_entry->model, file);
|
||||
if (!info)
|
||||
return FALSE;
|
||||
|
||||
return _gtk_file_info_consider_as_directory (info);
|
||||
}
|
||||
|
@@ -479,3 +479,12 @@ _gtk_file_info_get_icon (GFileInfo *info,
|
||||
icon = g_themed_icon_new ("text-x-generic");
|
||||
return icon;
|
||||
}
|
||||
|
||||
GFile *
|
||||
_gtk_file_info_get_file (GFileInfo *info)
|
||||
{
|
||||
g_assert (G_IS_FILE_INFO (info));
|
||||
g_assert (g_file_info_has_attribute (info, "standard::file"));
|
||||
|
||||
return G_FILE (g_file_info_get_attribute_object (info, "standard::file"));
|
||||
}
|
||||
|
@@ -58,6 +58,8 @@ GIcon * _gtk_file_info_get_icon (GFileInfo *info,
|
||||
int scale,
|
||||
GtkIconTheme *icon_theme);
|
||||
|
||||
GFile * _gtk_file_info_get_file (GFileInfo *info);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_FILE_CHOOSER_UTILS_H__ */
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -23,6 +23,7 @@
|
||||
|
||||
#include <glib.h>
|
||||
#include "gtkfilechooserwidget.h"
|
||||
#include "gtkselectionmodel.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@@ -36,6 +37,12 @@ gtk_file_chooser_widget_should_respond (GtkFileChooserWidget *chooser);
|
||||
void
|
||||
gtk_file_chooser_widget_initial_focus (GtkFileChooserWidget *chooser);
|
||||
|
||||
GSList *
|
||||
gtk_file_chooser_widget_get_selected_files (GtkFileChooserWidget *impl);
|
||||
|
||||
GtkSelectionModel *
|
||||
gtk_file_chooser_widget_get_selection_model (GtkFileChooserWidget *chooser);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_FILE_CHOOSER_WIDGET_PRIVATE_H__ */
|
||||
|
914
gtk/gtkfiledialog.c
Normal file
914
gtk/gtkfiledialog.c
Normal file
@@ -0,0 +1,914 @@
|
||||
/*
|
||||
* GTK - The GIMP Toolkit
|
||||
* Copyright (C) 2022 Red Hat, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This Library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This Library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkfiledialog.h"
|
||||
|
||||
#include "gtk/gtkchoice.h"
|
||||
#include "gtkfilechooserdialog.h"
|
||||
#include <glib/gi18n-lib.h>
|
||||
|
||||
/**
|
||||
* GtkFileDialog:
|
||||
*
|
||||
* A `GtkFileDialog` object collects the arguments that
|
||||
* are needed to present a file chooser dialog to the
|
||||
* user, such as a title for the dialog and whether it
|
||||
* should be modal.
|
||||
*
|
||||
* The dialog is shown with the [function@Gtk.FileDialog.choose_rgba]
|
||||
* function. This API follows the GIO async pattern, and the
|
||||
* result can be obtained by calling
|
||||
* [function@Gtk.FileDialog.choose_rgba_finish].
|
||||
*
|
||||
* See [class@Gtk.FileDialogButton] for a convenient control
|
||||
* that uses `GtkFileDialog` and presents the results.
|
||||
*
|
||||
* `GtkFileDialog was added in GTK 4.10.
|
||||
*/
|
||||
/* {{{ GObject implementation */
|
||||
|
||||
struct _GtkFileDialog
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
char *title;
|
||||
unsigned int modal : 1;
|
||||
unsigned int select_multiple : 1;
|
||||
unsigned int create_folders : 1;
|
||||
|
||||
GListModel *filters;
|
||||
GListModel *shortcuts;
|
||||
GListModel *choices;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_TITLE = 1,
|
||||
PROP_MODAL,
|
||||
PROP_SELECT_MULTIPLE,
|
||||
PROP_CREATE_FOLDERS,
|
||||
PROP_FILTERS,
|
||||
PROP_SHORTCUTS,
|
||||
PROP_CHOICES,
|
||||
|
||||
NUM_PROPERTIES
|
||||
};
|
||||
|
||||
static GParamSpec *properties[NUM_PROPERTIES];
|
||||
|
||||
G_DEFINE_TYPE (GtkFileDialog, gtk_file_dialog, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
gtk_file_dialog_init (GtkFileDialog *self)
|
||||
{
|
||||
self->title = g_strdup (_("Pick a File"));
|
||||
self->modal = TRUE;
|
||||
self->create_folders = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_file_dialog_finalize (GObject *object)
|
||||
{
|
||||
GtkFileDialog *self = GTK_FILE_DIALOG (object);
|
||||
|
||||
g_free (self->title);
|
||||
g_clear_object (&self->filters);
|
||||
g_clear_object (&self->shortcuts);
|
||||
g_clear_object (&self->choices);
|
||||
|
||||
G_OBJECT_CLASS (gtk_file_dialog_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_file_dialog_get_property (GObject *object,
|
||||
unsigned int property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkFileDialog *self = GTK_FILE_DIALOG (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_TITLE:
|
||||
g_value_set_string (value, self->title);
|
||||
break;
|
||||
|
||||
case PROP_MODAL:
|
||||
g_value_set_boolean (value, self->modal);
|
||||
break;
|
||||
|
||||
case PROP_SELECT_MULTIPLE:
|
||||
g_value_set_boolean (value, self->select_multiple);
|
||||
break;
|
||||
|
||||
case PROP_CREATE_FOLDERS:
|
||||
g_value_set_boolean (value, self->create_folders);
|
||||
break;
|
||||
|
||||
case PROP_FILTERS:
|
||||
g_value_set_object (value, self->filters);
|
||||
break;
|
||||
|
||||
case PROP_SHORTCUTS:
|
||||
g_value_set_object (value, self->shortcuts);
|
||||
break;
|
||||
|
||||
case PROP_CHOICES:
|
||||
g_value_set_object (value, self->choices);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_file_dialog_set_property (GObject *object,
|
||||
unsigned int prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkFileDialog *self = GTK_FILE_DIALOG (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_TITLE:
|
||||
gtk_file_dialog_set_title (self, g_value_get_string (value));
|
||||
break;
|
||||
|
||||
case PROP_MODAL:
|
||||
gtk_file_dialog_set_modal (self, g_value_get_boolean (value));
|
||||
break;
|
||||
|
||||
case PROP_SELECT_MULTIPLE:
|
||||
gtk_file_dialog_set_select_multiple (self, g_value_get_boolean (value));
|
||||
break;
|
||||
|
||||
case PROP_CREATE_FOLDERS:
|
||||
gtk_file_dialog_set_create_folders (self, g_value_get_boolean (value));
|
||||
break;
|
||||
|
||||
case PROP_FILTERS:
|
||||
gtk_file_dialog_set_filters (self, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
case PROP_SHORTCUTS:
|
||||
gtk_file_dialog_set_shortcuts (self, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
case PROP_CHOICES:
|
||||
gtk_file_dialog_set_choices (self, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_file_dialog_class_init (GtkFileDialogClass *class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
|
||||
object_class->finalize = gtk_file_dialog_finalize;
|
||||
object_class->get_property = gtk_file_dialog_get_property;
|
||||
object_class->set_property = gtk_file_dialog_set_property;
|
||||
|
||||
/**
|
||||
* GtkFileDialog:title: (attributes org.gtk.Property.get=gtk_file_dialog_get_title org.gtk.Property.set=gtk_color_dialog_set_title)
|
||||
*
|
||||
* A title that may be shown on the file chooser
|
||||
* dialog that is presented by [function@Gtk.FileDialog.choose_rgba].
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
properties[PROP_TITLE] =
|
||||
g_param_spec_string ("title", NULL, NULL,
|
||||
NULL,
|
||||
G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS|G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GtkFileDialog:modal: (attributes org.gtk.Property.get=gtk_file_dialog_get_modal org.gtk.Property.set=gtk_color_dialog_set_modal)
|
||||
*
|
||||
* Whether the file chooser dialog is modal.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
properties[PROP_MODAL] =
|
||||
g_param_spec_boolean ("modal", NULL, NULL,
|
||||
TRUE,
|
||||
G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS|G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GtkFileDialog:select-multiple: (attributes org.gtk.Property.get=gtk_file_dialog_get_select_multiple org.gtk.Property.set=gtk_color_dialog_set_select_multiple)
|
||||
*
|
||||
* Whether the file chooser dialog allows to select more than one file.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
properties[PROP_SELECT_MULTIPLE] =
|
||||
g_param_spec_boolean ("select-multiple", NULL, NULL,
|
||||
FALSE,
|
||||
G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS|G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GtkFileDialog:create-folders: (attributes org.gtk.Property.get=gtk_file_dialog_get_create_folders org.gtk.Property.set=gtk_color_dialog_set_create_folders)
|
||||
*
|
||||
* Whether the file chooser dialog will allow to create new folders.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
properties[PROP_CREATE_FOLDERS] =
|
||||
g_param_spec_boolean ("create-folders", NULL, NULL,
|
||||
TRUE,
|
||||
G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS|G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
properties[PROP_FILTERS] =
|
||||
g_param_spec_object ("filters", NULL, NULL,
|
||||
G_TYPE_LIST_MODEL,
|
||||
G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS|G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
properties[PROP_SHORTCUTS] =
|
||||
g_param_spec_object ("shortcuts", NULL, NULL,
|
||||
G_TYPE_LIST_MODEL,
|
||||
G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS|G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
properties[PROP_CHOICES] =
|
||||
g_param_spec_object ("choices", NULL, NULL,
|
||||
G_TYPE_LIST_MODEL,
|
||||
G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS|G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
g_object_class_install_properties (object_class, NUM_PROPERTIES, properties);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Utilities */
|
||||
|
||||
static void
|
||||
file_chooser_set_filters (GtkFileChooser *chooser,
|
||||
GListModel *filters)
|
||||
{
|
||||
if (!filters)
|
||||
return;
|
||||
|
||||
for (unsigned int i = 0; i < g_list_model_get_n_items (filters); i++)
|
||||
{
|
||||
GtkFileFilter *filter = g_list_model_get_item (filters, i);
|
||||
gtk_file_chooser_add_filter (chooser, filter);
|
||||
g_object_unref (filter);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
file_chooser_set_shortcuts (GtkFileChooser *chooser,
|
||||
GListModel *shortcuts)
|
||||
{
|
||||
if (!shortcuts)
|
||||
return;
|
||||
|
||||
for (unsigned int i = 0; i < g_list_model_get_n_items (shortcuts); i++)
|
||||
{
|
||||
GFile *shortcut = g_list_model_get_item (shortcuts, i);
|
||||
gtk_file_chooser_add_shortcut_folder (chooser, shortcut, NULL);
|
||||
g_object_unref (shortcut);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
file_chooser_set_choices (GtkFileChooser *chooser,
|
||||
GListModel *choices)
|
||||
{
|
||||
if (!choices)
|
||||
return;
|
||||
|
||||
for (unsigned int i = 0; i < g_list_model_get_n_items (choices); i++)
|
||||
{
|
||||
GtkChoice *choice = g_list_model_get_item (choices, i);
|
||||
char *id;
|
||||
const char *label;
|
||||
char **options;
|
||||
const char * const *option_labels;
|
||||
|
||||
label = gtk_choice_get_label (choice);
|
||||
option_labels = gtk_choice_get_options (choice);
|
||||
|
||||
id = g_strdup_printf ("choice %u", i);
|
||||
|
||||
if (option_labels)
|
||||
{
|
||||
GStrvBuilder *strv = g_strv_builder_new ();
|
||||
|
||||
for (unsigned int j = 0; option_labels[j]; j++)
|
||||
{
|
||||
char *option = g_strdup_printf ("option %u", j);
|
||||
g_strv_builder_add (strv, option);
|
||||
g_free (option);
|
||||
}
|
||||
|
||||
options = g_strv_builder_end (strv);
|
||||
}
|
||||
else
|
||||
options = NULL;
|
||||
|
||||
gtk_file_chooser_add_choice (chooser, id, label, (const char **)options, (const char **)option_labels);
|
||||
|
||||
g_free (id);
|
||||
g_strfreev (options);
|
||||
|
||||
g_object_unref (choice);
|
||||
}
|
||||
}
|
||||
|
||||
static char **
|
||||
file_chooser_get_options (GtkFileChooser *chooser,
|
||||
GListModel *choices)
|
||||
{
|
||||
GStrvBuilder *strv;
|
||||
|
||||
if (!choices)
|
||||
return NULL;
|
||||
|
||||
strv = g_strv_builder_new ();
|
||||
|
||||
for (unsigned int i = 0; i < g_list_model_get_n_items (choices); i++)
|
||||
{
|
||||
GtkChoice *choice = g_list_model_get_item (choices, i);
|
||||
char *id;
|
||||
const char *option;
|
||||
unsigned int pos;
|
||||
const char *option_label;
|
||||
|
||||
id = g_strdup_printf ("choice %u", i);
|
||||
|
||||
option = gtk_file_chooser_get_choice (chooser, id);
|
||||
|
||||
pos = (unsigned int) g_ascii_strtoull (option + strlen ("option "), NULL, 10);
|
||||
|
||||
option_label = gtk_choice_get_options (choice)[pos];
|
||||
|
||||
g_strv_builder_add (strv, option_label);
|
||||
|
||||
g_free (id);
|
||||
g_object_unref (choice);
|
||||
}
|
||||
|
||||
return g_strv_builder_end (strv);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Public API */
|
||||
/* {{{ Constructor */
|
||||
|
||||
/**
|
||||
* gtk_file_dialog_new:
|
||||
*
|
||||
* Creates a new `GtkFileDialog` object.
|
||||
*
|
||||
* Returns: the new `GtkFileDialog`
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
GtkFileDialog *
|
||||
gtk_file_dialog_new (void)
|
||||
{
|
||||
return g_object_new (GTK_TYPE_FILE_DIALOG, NULL);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Getters and setters */
|
||||
|
||||
/**
|
||||
* gtk_file_dialog_get_title:
|
||||
* @self: a `GtkFileDialog`
|
||||
*
|
||||
* Returns the title that will be shown on the
|
||||
* file chooser dialog.
|
||||
*
|
||||
* Returns: the title
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
const char *
|
||||
gtk_file_dialog_get_title (GtkFileDialog *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_FILE_DIALOG (self), NULL);
|
||||
|
||||
return self->title;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_file_dialog_set_title:
|
||||
* @self: a `GtkFileDialog`
|
||||
* @title: the new title
|
||||
*
|
||||
* Sets the title that will be shown on the
|
||||
* file chooser dialog.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
void
|
||||
gtk_file_dialog_set_title (GtkFileDialog *self,
|
||||
const char *title)
|
||||
{
|
||||
char *new_title;
|
||||
|
||||
g_return_if_fail (GTK_IS_FILE_DIALOG (self));
|
||||
g_return_if_fail (title != NULL);
|
||||
|
||||
if (g_strcmp0 (self->title, title) == 0)
|
||||
return;
|
||||
|
||||
new_title = g_strdup (title);
|
||||
g_free (self->title);
|
||||
self->title = new_title;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_TITLE]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_file_dialog_get_modal:
|
||||
* @self: a `GtkFileDialog`
|
||||
*
|
||||
* Returns whether the file chooser dialog
|
||||
* blocks interaction with the parent window
|
||||
* while it is presented.
|
||||
*
|
||||
* Returns: `TRUE` if the file chooser dialog is modal
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
gboolean
|
||||
gtk_file_dialog_get_modal (GtkFileDialog *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_FILE_DIALOG (self), TRUE);
|
||||
|
||||
return self->modal;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_file_dialog_set_modal:
|
||||
* @self: a `GtkFileDialog`
|
||||
* @modal: the new value
|
||||
*
|
||||
* Sets whether the file chooser dialog
|
||||
* blocks interaction with the parent window
|
||||
* while it is presented.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
void
|
||||
gtk_file_dialog_set_modal (GtkFileDialog *self,
|
||||
gboolean modal)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_FILE_DIALOG (self));
|
||||
|
||||
if (self->modal == modal)
|
||||
return;
|
||||
|
||||
self->modal = modal;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_MODAL]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_file_dialog_get_select_multiple:
|
||||
* @self: a `GtkFileDialog`
|
||||
*
|
||||
* Returns whether the file chooser dialog
|
||||
* allows to select multiple files.
|
||||
*
|
||||
* Returns: `TRUE` if the file chooser dialog allows multi-selection
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
gboolean
|
||||
gtk_file_dialog_get_select_multiple (GtkFileDialog *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_FILE_DIALOG (self), FALSE);
|
||||
|
||||
return self->select_multiple;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_file_dialog_set_select_multiple:
|
||||
* @self: a `GtkFileDialog`
|
||||
* @modal: the new value
|
||||
*
|
||||
* Sets whether the file chooser dialog
|
||||
* allows to select multiple files.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
void
|
||||
gtk_file_dialog_set_select_multiple (GtkFileDialog *self,
|
||||
gboolean select_multiple)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_FILE_DIALOG (self));
|
||||
|
||||
if (self->select_multiple == select_multiple)
|
||||
return;
|
||||
|
||||
self->select_multiple = select_multiple;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SELECT_MULTIPLE]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_file_dialog_get_create_folders:
|
||||
* @self: a `GtkFileDialog`
|
||||
*
|
||||
* Returns whether the file chooser dialog
|
||||
* allows to create folders.
|
||||
*
|
||||
* Returns: `TRUE` if the file chooser dialog allows folder creation
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
gboolean
|
||||
gtk_file_dialog_get_create_folders (GtkFileDialog *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_FILE_DIALOG (self), FALSE);
|
||||
|
||||
return self->create_folders;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_file_dialog_set_create_folders:
|
||||
* @self: a `GtkFileDialog`
|
||||
* @modal: the new value
|
||||
*
|
||||
* Sets whether the file chooser dialog
|
||||
* allows to create folders.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
void
|
||||
gtk_file_dialog_set_create_folders (GtkFileDialog *self,
|
||||
gboolean create_folders)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_FILE_DIALOG (self));
|
||||
|
||||
if (self->create_folders == create_folders)
|
||||
return;
|
||||
|
||||
self->create_folders = create_folders;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_CREATE_FOLDERS]);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_file_dialog_set_filters (GtkFileDialog *self,
|
||||
GListModel *filters)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_FILE_DIALOG (self));
|
||||
g_return_if_fail (G_IS_LIST_MODEL (filters));
|
||||
g_return_if_fail (g_list_model_get_item_type (G_LIST_MODEL (filters)) == GTK_TYPE_FILE_FILTER);
|
||||
|
||||
if (!g_set_object (&self->filters, filters))
|
||||
return;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FILTERS]);
|
||||
}
|
||||
|
||||
GListModel *
|
||||
gtk_file_dialog_get_filters (GtkFileDialog *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_FILE_DIALOG (self), NULL);
|
||||
|
||||
return self->filters;
|
||||
}
|
||||
|
||||
void
|
||||
gtk_file_dialog_set_shortcuts (GtkFileDialog *self,
|
||||
GListModel *shortcuts)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_FILE_DIALOG (self));
|
||||
g_return_if_fail (G_IS_LIST_MODEL (shortcuts));
|
||||
g_return_if_fail (g_list_model_get_item_type (G_LIST_MODEL (shortcuts)) == G_TYPE_FILE);
|
||||
|
||||
if (!g_set_object (&self->shortcuts, shortcuts))
|
||||
return;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SHORTCUTS]);
|
||||
}
|
||||
|
||||
GListModel *
|
||||
gtk_file_dialog_get_shortcuts (GtkFileDialog *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_FILE_DIALOG (self), NULL);
|
||||
|
||||
return self->shortcuts;
|
||||
}
|
||||
|
||||
void
|
||||
gtk_file_dialog_set_choices (GtkFileDialog *self,
|
||||
GListModel *choices)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_FILE_DIALOG (self));
|
||||
g_return_if_fail (G_IS_LIST_MODEL (choices));
|
||||
g_return_if_fail (g_list_model_get_item_type (G_LIST_MODEL (choices)) == GTK_TYPE_CHOICE);
|
||||
|
||||
if (!g_set_object (&self->choices, choices))
|
||||
return;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_CHOICES]);
|
||||
}
|
||||
|
||||
GListModel *
|
||||
gtk_file_dialog_get_choices (GtkFileDialog *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_FILE_DIALOG (self), NULL);
|
||||
|
||||
return self->choices;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Async API */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GListModel *files;
|
||||
char **options;
|
||||
} FileResult;
|
||||
|
||||
static void response_cb (GTask *task,
|
||||
int response);
|
||||
|
||||
static void
|
||||
cancelled_cb (GCancellable *cancellable,
|
||||
GTask *task)
|
||||
{
|
||||
response_cb (task, GTK_RESPONSE_CANCEL);
|
||||
}
|
||||
|
||||
static void
|
||||
response_cb (GTask *task,
|
||||
int response)
|
||||
{
|
||||
GCancellable *cancellable;
|
||||
|
||||
cancellable = g_task_get_cancellable (task);
|
||||
|
||||
if (cancellable)
|
||||
g_signal_handlers_disconnect_by_func (cancellable, cancelled_cb, task);
|
||||
|
||||
if (response == GTK_RESPONSE_OK)
|
||||
{
|
||||
GtkFileDialog *self;
|
||||
GtkFileChooserDialog *window;
|
||||
FileResult file_result;
|
||||
|
||||
self = GTK_FILE_DIALOG (g_task_get_source_object (task));
|
||||
window = GTK_FILE_CHOOSER_DIALOG (g_task_get_task_data (task));
|
||||
|
||||
file_result.files = gtk_file_chooser_get_files (GTK_FILE_CHOOSER (window));
|
||||
file_result.options = file_chooser_get_options (GTK_FILE_CHOOSER (window),
|
||||
gtk_file_dialog_get_choices (self));
|
||||
|
||||
g_task_return_pointer (task, &file_result, NULL);
|
||||
}
|
||||
else
|
||||
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_CANCELLED, "Cancelled");
|
||||
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static void
|
||||
dialog_response (GtkDialog *dialog,
|
||||
int response,
|
||||
GTask *task)
|
||||
{
|
||||
response_cb (task, response);
|
||||
}
|
||||
|
||||
static GtkFileChooserDialog *
|
||||
create_file_chooser_dialog (GtkFileDialog *self,
|
||||
GtkWindow *parent,
|
||||
GtkFileChooserAction action)
|
||||
{
|
||||
GtkWidget *window;
|
||||
const char *accept[] = {
|
||||
N_("_Open"), N_("_Save"), N_("_Select")
|
||||
};
|
||||
|
||||
window = gtk_file_chooser_dialog_new (self->title, parent,
|
||||
action,
|
||||
_("_Cancel"), GTK_RESPONSE_CANCEL,
|
||||
_(accept[action]), GTK_RESPONSE_OK,
|
||||
NULL);
|
||||
gtk_window_set_modal (GTK_WINDOW (window), self->modal);
|
||||
gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (window), self->select_multiple);
|
||||
gtk_file_chooser_set_create_folders (GTK_FILE_CHOOSER (window), self->create_folders);
|
||||
|
||||
file_chooser_set_filters (GTK_FILE_CHOOSER (window), self->filters);
|
||||
file_chooser_set_shortcuts (GTK_FILE_CHOOSER (window), self->shortcuts);
|
||||
file_chooser_set_choices (GTK_FILE_CHOOSER (window), self->choices);
|
||||
|
||||
return GTK_FILE_CHOOSER_DIALOG (window);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
finish_file_op (GtkFileDialog *self,
|
||||
GAsyncResult *result,
|
||||
GListModel **files,
|
||||
char ***options,
|
||||
GError **error)
|
||||
{
|
||||
FileResult *ret;
|
||||
|
||||
ret = g_task_propagate_pointer (G_TASK (result), error);
|
||||
if (ret)
|
||||
{
|
||||
*files = ret->files;
|
||||
if (options)
|
||||
*options = ret->options;
|
||||
else
|
||||
g_strfreev (ret->options);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_file_dialog_open:
|
||||
* @self: a `GtkFileDialog`
|
||||
* @parent: (nullable): the parent `GtkWindow`
|
||||
* @initial_file: (nullable): the file to select initially
|
||||
* @cancellable: (nullable): a `GCancellable` to cancel the operation
|
||||
* @callback: (scope async): a callback to call when the operation is complete
|
||||
* @user_data: (closure callback): data to pass to @callback
|
||||
*
|
||||
* This function initiates a file selection operation by
|
||||
* presenting a file chooser dialog to the user.
|
||||
*
|
||||
* The @callback will be called when the dialog is dismissed.
|
||||
* It should call [function@Gtk.FileDialog.open_finish]
|
||||
* to obtain the result.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
void
|
||||
gtk_file_dialog_open (GtkFileDialog *self,
|
||||
GtkWindow *parent,
|
||||
GFile *initial_file,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkFileChooserDialog *window;
|
||||
GTask *task;
|
||||
|
||||
g_return_if_fail (GTK_IS_FILE_DIALOG (self));
|
||||
|
||||
window = create_file_chooser_dialog (self, parent, GTK_FILE_CHOOSER_ACTION_OPEN);
|
||||
|
||||
if (initial_file)
|
||||
gtk_file_chooser_set_file (GTK_FILE_CHOOSER (window), initial_file, NULL);
|
||||
|
||||
task = g_task_new (self, cancellable, callback, user_data);
|
||||
g_task_set_source_tag (task, gtk_file_dialog_open);
|
||||
g_task_set_task_data (task, window, (GDestroyNotify) gtk_window_destroy);
|
||||
|
||||
if (cancellable)
|
||||
g_signal_connect (cancellable, "cancelled", G_CALLBACK (cancelled_cb), task);
|
||||
|
||||
g_signal_connect (window, "response", G_CALLBACK (dialog_response), task);
|
||||
|
||||
gtk_window_present (GTK_WINDOW (window));
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_file_dialog_open_finish:
|
||||
* @self: a `GtkFileDialog`
|
||||
* @result: a `GAsyncResult`
|
||||
* @files: (out caller-allocates): return location for the selected files
|
||||
* @options: (out caller-allocates): return location for choices
|
||||
* @error: return location for an error
|
||||
*
|
||||
* Finishes the [function@Gtk.FileDialog.open] call and
|
||||
* returns the resulting files as a `GListModel` of `GFiles`.
|
||||
*
|
||||
* Returns: `TRUE` if a file was selected. Otherwise,
|
||||
* `FALSE` is returned and @error is set
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
gboolean
|
||||
gtk_file_dialog_open_finish (GtkFileDialog *self,
|
||||
GAsyncResult *result,
|
||||
GListModel **files,
|
||||
char ***options,
|
||||
GError **error)
|
||||
{
|
||||
return finish_file_op (self, result, files, options, error);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_file_dialog_select_folder (GtkFileDialog *self,
|
||||
GtkWindow *parent,
|
||||
GFile *current_folder,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkFileChooserDialog *window;
|
||||
GTask *task;
|
||||
|
||||
g_return_if_fail (GTK_IS_FILE_DIALOG (self));
|
||||
|
||||
window = create_file_chooser_dialog (self, parent, GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
|
||||
|
||||
if (current_folder)
|
||||
gtk_file_chooser_set_file (GTK_FILE_CHOOSER (window), current_folder, NULL);
|
||||
|
||||
task = g_task_new (self, cancellable, callback, user_data);
|
||||
g_task_set_source_tag (task, gtk_file_dialog_select_folder);
|
||||
g_task_set_task_data (task, window, (GDestroyNotify) gtk_window_destroy);
|
||||
|
||||
if (cancellable)
|
||||
g_signal_connect (cancellable, "cancelled", G_CALLBACK (cancelled_cb), task);
|
||||
|
||||
g_signal_connect (window, "response", G_CALLBACK (dialog_response), task);
|
||||
|
||||
gtk_window_present (GTK_WINDOW (window));
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_file_dialog_select_folder_finish (GtkFileDialog *self,
|
||||
GAsyncResult *result,
|
||||
GListModel **files,
|
||||
char ***options,
|
||||
GError **error)
|
||||
{
|
||||
return finish_file_op (self, result, files, options, error);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_file_dialog_save (GtkFileDialog *self,
|
||||
GtkWindow *parent,
|
||||
GFile *current_folder,
|
||||
const char *current_name,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkFileChooserDialog *window;
|
||||
GTask *task;
|
||||
|
||||
g_return_if_fail (GTK_IS_FILE_DIALOG (self));
|
||||
|
||||
window = create_file_chooser_dialog (self, parent, GTK_FILE_CHOOSER_ACTION_SAVE);
|
||||
|
||||
if (current_folder)
|
||||
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (window), current_folder, NULL);
|
||||
if (current_name)
|
||||
gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (window), current_name);
|
||||
|
||||
task = g_task_new (self, cancellable, callback, user_data);
|
||||
g_task_set_source_tag (task, gtk_file_dialog_save);
|
||||
g_task_set_task_data (task, window, (GDestroyNotify) gtk_window_destroy);
|
||||
|
||||
if (cancellable)
|
||||
g_signal_connect (cancellable, "cancelled", G_CALLBACK (cancelled_cb), task);
|
||||
|
||||
g_signal_connect (window, "response", G_CALLBACK (dialog_response), task);
|
||||
|
||||
gtk_window_present (GTK_WINDOW (window));
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_file_dialog_save_finish (GtkFileDialog *self,
|
||||
GAsyncResult *result,
|
||||
GListModel **files,
|
||||
char ***options,
|
||||
GError **error)
|
||||
{
|
||||
return finish_file_op (self, result, files, options, error);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* }}} */
|
||||
|
||||
/* vim:set foldmethod=marker expandtab: */
|
130
gtk/gtkfiledialog.h
Normal file
130
gtk/gtkfiledialog.h
Normal file
@@ -0,0 +1,130 @@
|
||||
/* GTK - The GIMP Toolkit
|
||||
*
|
||||
* Copyright (C) 2022 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gtk/gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <gtk/gtkwindow.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_FILE_DIALOG (gtk_file_dialog_get_type ())
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
G_DECLARE_FINAL_TYPE (GtkFileDialog, gtk_file_dialog, GTK, FILE_DIALOG, GObject)
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
GtkFileDialog * gtk_file_dialog_new (void);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
const char * gtk_file_dialog_get_title (GtkFileDialog *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
void gtk_file_dialog_set_title (GtkFileDialog *self,
|
||||
const char *title);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
gboolean gtk_file_dialog_get_modal (GtkFileDialog *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
void gtk_file_dialog_set_modal (GtkFileDialog *self,
|
||||
gboolean modal);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
gboolean gtk_file_dialog_get_select_multiple (GtkFileDialog *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
void gtk_file_dialog_set_select_multiple (GtkFileDialog *self,
|
||||
gboolean select_multiple);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
gboolean gtk_file_dialog_get_create_folders (GtkFileDialog *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
void gtk_file_dialog_set_create_folders (GtkFileDialog *self,
|
||||
gboolean create_folders);
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
void gtk_file_dialog_set_filters (GtkFileDialog *self,
|
||||
GListModel *filters);
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
GListModel * gtk_file_dialog_get_filters (GtkFileDialog *dialog);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
void gtk_file_dialog_set_shortcuts (GtkFileDialog *self,
|
||||
GListModel *filters);
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
GListModel * gtk_file_dialog_get_shortcuts (GtkFileDialog *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
void gtk_file_dialog_set_choices (GtkFileDialog *self,
|
||||
GListModel *filters);
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
GListModel * gtk_file_dialog_get_choices (GtkFileDialog *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
void gtk_file_dialog_open (GtkFileDialog *self,
|
||||
GtkWindow *parent,
|
||||
GFile *current_file,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
gboolean gtk_file_dialog_open_finish (GtkFileDialog *self,
|
||||
GAsyncResult *result,
|
||||
GListModel **files,
|
||||
char ***options,
|
||||
GError **error);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
void gtk_file_dialog_select_folder (GtkFileDialog *self,
|
||||
GtkWindow *parent,
|
||||
GFile *current_folder,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
gboolean gtk_file_dialog_select_folder_finish
|
||||
(GtkFileDialog *self,
|
||||
GAsyncResult *result,
|
||||
GListModel **files,
|
||||
char ***options,
|
||||
GError **error);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
void gtk_file_dialog_save (GtkFileDialog *dialog,
|
||||
GtkWindow *parent,
|
||||
GFile *current_folder,
|
||||
const char *current_name,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
gboolean gtk_file_dialog_save_finish (GtkFileDialog *self,
|
||||
GAsyncResult *result,
|
||||
GListModel **files,
|
||||
char ***choices,
|
||||
GError **error);
|
||||
|
||||
G_END_DECLS
|
File diff suppressed because it is too large
Load Diff
@@ -21,7 +21,6 @@
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include <gtk/gtkfilefilter.h>
|
||||
#include <gtk/deprecated/gtktreemodel.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@@ -33,39 +32,13 @@ typedef struct _GtkFileSystemModel GtkFileSystemModel;
|
||||
|
||||
GType _gtk_file_system_model_get_type (void) G_GNUC_CONST;
|
||||
|
||||
typedef gboolean (*GtkFileSystemModelGetValue) (GtkFileSystemModel *model,
|
||||
GFile *file,
|
||||
GFileInfo *info,
|
||||
int column,
|
||||
GValue *value,
|
||||
gpointer user_data);
|
||||
|
||||
GtkFileSystemModel *_gtk_file_system_model_new (GtkFileSystemModelGetValue get_func,
|
||||
gpointer get_data,
|
||||
guint n_columns,
|
||||
...);
|
||||
GtkFileSystemModel *_gtk_file_system_model_new_for_directory(GFile * dir,
|
||||
const char * attributes,
|
||||
GtkFileSystemModelGetValue get_func,
|
||||
gpointer get_data,
|
||||
guint n_columns,
|
||||
...);
|
||||
GtkFileSystemModel *_gtk_file_system_model_new (void);
|
||||
GtkFileSystemModel *_gtk_file_system_model_new_for_directory(GFile *dir,
|
||||
const char *attributes);
|
||||
GFile * _gtk_file_system_model_get_directory (GtkFileSystemModel *model);
|
||||
GCancellable * _gtk_file_system_model_get_cancellable (GtkFileSystemModel *model);
|
||||
gboolean _gtk_file_system_model_iter_is_visible (GtkFileSystemModel *model,
|
||||
GtkTreeIter *iter);
|
||||
gboolean _gtk_file_system_model_iter_is_filtered_out (GtkFileSystemModel *model,
|
||||
GtkTreeIter *iter);
|
||||
GFileInfo * _gtk_file_system_model_get_info (GtkFileSystemModel *model,
|
||||
GtkTreeIter *iter);
|
||||
gboolean _gtk_file_system_model_get_iter_for_file(GtkFileSystemModel *model,
|
||||
GtkTreeIter *iter,
|
||||
GFileInfo * _gtk_file_system_model_get_info_for_file(GtkFileSystemModel *model,
|
||||
GFile *file);
|
||||
GFile * _gtk_file_system_model_get_file (GtkFileSystemModel *model,
|
||||
GtkTreeIter *iter);
|
||||
const GValue * _gtk_file_system_model_get_value (GtkFileSystemModel *model,
|
||||
GtkTreeIter * iter,
|
||||
int column);
|
||||
|
||||
void _gtk_file_system_model_add_and_query_file (GtkFileSystemModel *model,
|
||||
GFile *file,
|
||||
@@ -88,8 +61,6 @@ void _gtk_file_system_model_set_show_files (GtkFileSystemModel
|
||||
gboolean show_files);
|
||||
void _gtk_file_system_model_set_filter_folders (GtkFileSystemModel *model,
|
||||
gboolean show_folders);
|
||||
void _gtk_file_system_model_clear_cache (GtkFileSystemModel *model,
|
||||
int column);
|
||||
|
||||
void _gtk_file_system_model_set_filter (GtkFileSystemModel *model,
|
||||
GtkFileFilter *filter);
|
||||
|
255
gtk/gtkfilethumbnail.c
Normal file
255
gtk/gtkfilethumbnail.c
Normal file
@@ -0,0 +1,255 @@
|
||||
/* gtkfilethumbnail.c
|
||||
*
|
||||
* Copyright 2022 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkfilethumbnail.h"
|
||||
|
||||
#include "gtkbinlayout.h"
|
||||
#include "gtkfilechooserutils.h"
|
||||
#include "gtkimage.h"
|
||||
#include "gtkprivate.h"
|
||||
#include "gtkwidget.h"
|
||||
|
||||
#define ICON_SIZE 16
|
||||
|
||||
struct _GtkFileThumbnail
|
||||
{
|
||||
GtkWidget parent;
|
||||
|
||||
GtkWidget *image;
|
||||
|
||||
GCancellable *cancellable;
|
||||
GFileInfo *info;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GtkWidgetClass parent;
|
||||
} GtkFileThumbnailClass;
|
||||
|
||||
G_DEFINE_FINAL_TYPE (GtkFileThumbnail, _gtk_file_thumbnail, GTK_TYPE_WIDGET)
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_INFO,
|
||||
N_PROPS,
|
||||
};
|
||||
|
||||
static GParamSpec *properties [N_PROPS];
|
||||
|
||||
static void
|
||||
copy_attribute (GFileInfo *to,
|
||||
GFileInfo *from,
|
||||
const char *attribute)
|
||||
{
|
||||
GFileAttributeType type;
|
||||
gpointer value;
|
||||
|
||||
if (g_file_info_get_attribute_data (from, attribute, &type, &value, NULL))
|
||||
g_file_info_set_attribute (to, attribute, type, value);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
update_image (GtkFileThumbnail *self)
|
||||
{
|
||||
GtkIconTheme *icon_theme;
|
||||
GIcon *icon;
|
||||
int scale;
|
||||
|
||||
if (!g_file_info_has_attribute (self->info, G_FILE_ATTRIBUTE_STANDARD_ICON))
|
||||
return FALSE;
|
||||
|
||||
scale = gtk_widget_get_scale_factor (GTK_WIDGET (self));
|
||||
icon_theme = gtk_icon_theme_get_for_display (gtk_widget_get_display (GTK_WIDGET (self)));
|
||||
|
||||
icon = _gtk_file_info_get_icon (self->info, ICON_SIZE, scale, icon_theme);
|
||||
|
||||
gtk_image_set_from_gicon (GTK_IMAGE (self->image), icon);
|
||||
|
||||
g_object_unref (icon);
|
||||
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
thumbnail_queried_cb (GObject *object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkFileThumbnail *self = user_data; /* might be unreffed if operation was cancelled */
|
||||
GFile *file = G_FILE (object);
|
||||
GFileInfo *queried;
|
||||
|
||||
queried = g_file_query_info_finish (file, result, NULL);
|
||||
if (queried == NULL)
|
||||
return;
|
||||
|
||||
copy_attribute (self->info, queried, G_FILE_ATTRIBUTE_THUMBNAIL_PATH);
|
||||
copy_attribute (self->info, queried, G_FILE_ATTRIBUTE_THUMBNAILING_FAILED);
|
||||
copy_attribute (self->info, queried, G_FILE_ATTRIBUTE_STANDARD_ICON);
|
||||
|
||||
update_image (self);
|
||||
|
||||
g_clear_object (&queried);
|
||||
|
||||
g_clear_object (&self->cancellable);
|
||||
}
|
||||
|
||||
static void
|
||||
cancel_thumbnail (GtkFileThumbnail *self)
|
||||
{
|
||||
g_cancellable_cancel (self->cancellable);
|
||||
g_clear_object (&self->cancellable);
|
||||
}
|
||||
|
||||
static void
|
||||
get_thumbnail (GtkFileThumbnail *self)
|
||||
{
|
||||
if (!self->info)
|
||||
return;
|
||||
|
||||
if (!update_image (self))
|
||||
{
|
||||
GFile *file;
|
||||
|
||||
if (g_file_info_has_attribute (self->info, "filechooser::queried"))
|
||||
return;
|
||||
|
||||
g_assert (self->cancellable == NULL);
|
||||
self->cancellable = g_cancellable_new ();
|
||||
|
||||
file = _gtk_file_info_get_file (self->info);
|
||||
g_file_info_set_attribute_boolean (self->info, "filechooser::queried", TRUE);
|
||||
g_file_query_info_async (file,
|
||||
G_FILE_ATTRIBUTE_THUMBNAIL_PATH ","
|
||||
G_FILE_ATTRIBUTE_THUMBNAILING_FAILED ","
|
||||
G_FILE_ATTRIBUTE_STANDARD_ICON,
|
||||
G_FILE_QUERY_INFO_NONE,
|
||||
G_PRIORITY_DEFAULT,
|
||||
self->cancellable,
|
||||
thumbnail_queried_cb,
|
||||
self);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_gtk_file_thumbnail_dispose (GObject *object)
|
||||
{
|
||||
GtkFileThumbnail *self = (GtkFileThumbnail *)object;
|
||||
|
||||
_gtk_file_thumbnail_set_info (self, NULL);
|
||||
|
||||
g_clear_pointer (&self->image, gtk_widget_unparent);
|
||||
|
||||
G_OBJECT_CLASS (_gtk_file_thumbnail_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
_gtk_file_thumbnail_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkFileThumbnail *self = GTK_FILE_THUMBNAIL (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_INFO:
|
||||
g_value_set_object (value, self->info);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_gtk_file_thumbnail_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkFileThumbnail *self = GTK_FILE_THUMBNAIL (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_INFO:
|
||||
_gtk_file_thumbnail_set_info (self, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_gtk_file_thumbnail_class_init (GtkFileThumbnailClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
object_class->dispose = _gtk_file_thumbnail_dispose;
|
||||
object_class->get_property = _gtk_file_thumbnail_get_property;
|
||||
object_class->set_property = _gtk_file_thumbnail_set_property;
|
||||
|
||||
properties[PROP_INFO] =
|
||||
g_param_spec_object ("file-info", NULL, NULL,
|
||||
G_TYPE_FILE_INFO,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (object_class, N_PROPS, properties);
|
||||
|
||||
gtk_widget_class_set_css_name (widget_class, I_("filethumbnail"));
|
||||
|
||||
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
|
||||
}
|
||||
|
||||
static void
|
||||
_gtk_file_thumbnail_init (GtkFileThumbnail *self)
|
||||
{
|
||||
self->image = gtk_image_new ();
|
||||
gtk_widget_set_parent (self->image, GTK_WIDGET (self));
|
||||
}
|
||||
|
||||
GFileInfo *
|
||||
_gtk_file_thumbnail_get_info (GtkFileThumbnail *self)
|
||||
{
|
||||
g_assert (GTK_IS_FILE_THUMBNAIL (self));
|
||||
|
||||
return self->info;
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_file_thumbnail_set_info (GtkFileThumbnail *self,
|
||||
GFileInfo *info)
|
||||
{
|
||||
g_assert (GTK_IS_FILE_THUMBNAIL (self));
|
||||
g_assert (info == NULL || G_IS_FILE_INFO (info));
|
||||
|
||||
if (g_set_object (&self->info, info))
|
||||
{
|
||||
cancel_thumbnail (self);
|
||||
get_thumbnail (self);
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_INFO]);
|
||||
}
|
||||
}
|
||||
|
46
gtk/gtkfilethumbnail.h
Normal file
46
gtk/gtkfilethumbnail.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/* gtkfilethumbnail.h
|
||||
*
|
||||
* Copyright 2022 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __GTK_FILE_THUMBNAIL_H__
|
||||
#define __GTK_FILE_THUMBNAIL_H__
|
||||
|
||||
#include <gio/gio.h>
|
||||
|
||||
#include "gtkfilesystemmodel.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_FILE_THUMBNAIL (_gtk_file_thumbnail_get_type ())
|
||||
#define GTK_FILE_THUMBNAIL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_FILE_THUMBNAIL, GtkFileThumbnail))
|
||||
#define GTK_IS_FILE_THUMBNAIL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_FILE_THUMBNAIL))
|
||||
|
||||
typedef struct _GtkFileThumbnail GtkFileThumbnail;
|
||||
|
||||
GType _gtk_file_thumbnail_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GFileInfo *_gtk_file_thumbnail_get_info (GtkFileThumbnail *self);
|
||||
void _gtk_file_thumbnail_set_info (GtkFileThumbnail *self,
|
||||
GFileInfo *info);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_FILE_THUMBNAIL_H__ */
|
||||
|
@@ -1870,9 +1870,7 @@ find_affected_text (GtkFontChooserWidget *fontchooser,
|
||||
|
||||
hb_ot_layout_table_find_script (hb_face, HB_OT_TAG_GSUB, script_tag, &script_index);
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
hb_ot_layout_script_find_language (hb_face, HB_OT_TAG_GSUB, script_index, lang_tag, &lang_index);
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
hb_ot_layout_script_select_language (hb_face, HB_OT_TAG_GSUB, script_index, 1, &lang_tag, &lang_index);
|
||||
|
||||
if (hb_ot_layout_language_find_feature (hb_face,
|
||||
HB_OT_TAG_GSUB,
|
||||
@@ -2013,9 +2011,7 @@ update_feature_label (GtkFontChooserWidget *fontchooser,
|
||||
|
||||
hb_ot_layout_table_find_script (hb_face, HB_OT_TAG_GSUB, script_tag, &script_index);
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
hb_ot_layout_script_find_language (hb_face, HB_OT_TAG_GSUB, script_index, lang_tag, &lang_index);
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
hb_ot_layout_script_select_language (hb_face, HB_OT_TAG_GSUB, script_index, 1, &lang_tag, &lang_index);
|
||||
|
||||
if (hb_ot_layout_language_find_feature (hb_face, HB_OT_TAG_GSUB, script_index, lang_index, item->tag, &feature_index))
|
||||
{
|
||||
@@ -2565,9 +2561,7 @@ gtk_font_chooser_widget_update_font_features (GtkFontChooserWidget *fontchooser)
|
||||
{
|
||||
hb_ot_layout_table_find_script (hb_face, table[i], script_tag, &script_index);
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
hb_ot_layout_script_find_language (hb_face, table[i], script_index, lang_tag, &lang_index);
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
hb_ot_layout_script_select_language (hb_face, table[i], script_index, 1, &lang_tag, &lang_index);
|
||||
|
||||
feat = features + n_features;
|
||||
count = G_N_ELEMENTS (features) - n_features;
|
||||
|
671
gtk/gtkfontdialog.c
Normal file
671
gtk/gtkfontdialog.c
Normal file
@@ -0,0 +1,671 @@
|
||||
/*
|
||||
* GTK - The GIMP Toolkit
|
||||
* Copyright (C) 2022 Red Hat, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This Library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This Library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkfontdialog.h"
|
||||
|
||||
#include "gtkfontchooserdialog.h"
|
||||
#include "gtkbutton.h"
|
||||
#include "gtktypebuiltins.h"
|
||||
#include <glib/gi18n-lib.h>
|
||||
|
||||
/**
|
||||
* GtkFontDialog:
|
||||
*
|
||||
* A `GtkFontDialog` object collects the arguments that
|
||||
* are needed to present a font chooser dialog to the
|
||||
* user, such as a title for the dialog and whether it
|
||||
* should be modal.
|
||||
*
|
||||
* The dialog is shown with the [function@Gtk.FontDialog.choose_font]
|
||||
* function. This API follows the GIO async pattern, and the
|
||||
* result can be obtained by calling
|
||||
* [function@Gtk.FontDialog.choose_font_finish].
|
||||
*
|
||||
* See [class@Gtk.FontDialogButton] for a convenient control
|
||||
* that uses `GtkFontDialog` and presents the results.
|
||||
*
|
||||
* `GtkFontDialog was added in GTK 4.10.
|
||||
*/
|
||||
|
||||
/* {{{ GObject implementation */
|
||||
|
||||
struct _GtkFontDialog
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
char *title;
|
||||
GtkFontChooserLevel level;
|
||||
PangoLanguage *language;
|
||||
PangoFontMap *fontmap;
|
||||
|
||||
unsigned int modal : 1;
|
||||
|
||||
GtkFontFilterFunc filter;
|
||||
gpointer filter_data;
|
||||
GDestroyNotify filter_data_destroy;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_TITLE = 1,
|
||||
PROP_MODAL,
|
||||
PROP_LEVEL,
|
||||
PROP_LANGUAGE,
|
||||
PROP_FONTMAP,
|
||||
|
||||
NUM_PROPERTIES
|
||||
};
|
||||
|
||||
static GParamSpec *properties[NUM_PROPERTIES];
|
||||
|
||||
G_DEFINE_TYPE (GtkFontDialog, gtk_font_dialog, G_TYPE_OBJECT)
|
||||
|
||||
#define DEFAULT_LEVEL (GTK_FONT_CHOOSER_LEVEL_FAMILY| \
|
||||
GTK_FONT_CHOOSER_LEVEL_STYLE| \
|
||||
GTK_FONT_CHOOSER_LEVEL_SIZE)
|
||||
|
||||
static void
|
||||
gtk_font_dialog_init (GtkFontDialog *self)
|
||||
{
|
||||
self->title = g_strdup (_("Pick a Font"));
|
||||
self->modal = TRUE;
|
||||
self->level = DEFAULT_LEVEL;
|
||||
self->language = pango_language_get_default ();
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_font_dialog_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkFontDialog *self = GTK_FONT_DIALOG (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_TITLE:
|
||||
g_value_set_string (value, self->title);
|
||||
break;
|
||||
|
||||
case PROP_MODAL:
|
||||
g_value_set_boolean (value, self->modal);
|
||||
break;
|
||||
|
||||
case PROP_LEVEL:
|
||||
g_value_set_flags (value, self->level);
|
||||
break;
|
||||
|
||||
case PROP_LANGUAGE:
|
||||
g_value_set_boxed (value, self->language);
|
||||
break;
|
||||
|
||||
case PROP_FONTMAP:
|
||||
g_value_set_object (value, self->fontmap);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_font_dialog_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkFontDialog *self = GTK_FONT_DIALOG (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_TITLE:
|
||||
gtk_font_dialog_set_title (self, g_value_get_string (value));
|
||||
break;
|
||||
|
||||
case PROP_MODAL:
|
||||
gtk_font_dialog_set_modal (self, g_value_get_boolean (value));
|
||||
break;
|
||||
|
||||
case PROP_LEVEL:
|
||||
gtk_font_dialog_set_level (self, g_value_get_flags (value));
|
||||
break;
|
||||
|
||||
case PROP_LANGUAGE:
|
||||
gtk_font_dialog_set_language (self, g_value_get_boxed (value));
|
||||
break;
|
||||
|
||||
case PROP_FONTMAP:
|
||||
gtk_font_dialog_set_fontmap (self, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_font_dialog_finalize (GObject *object)
|
||||
{
|
||||
GtkFontDialog *self = GTK_FONT_DIALOG (object);
|
||||
|
||||
g_free (self->title);
|
||||
g_clear_object (&self->fontmap);
|
||||
g_clear_pointer (&self->filter_data, self->filter_data_destroy);
|
||||
|
||||
G_OBJECT_CLASS (gtk_font_dialog_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_font_dialog_class_init (GtkFontDialogClass *class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
|
||||
object_class->get_property = gtk_font_dialog_get_property;
|
||||
object_class->set_property = gtk_font_dialog_set_property;
|
||||
object_class->finalize = gtk_font_dialog_finalize;
|
||||
|
||||
/**
|
||||
* GtkFontDialog:title: (attributes org.gtk.Property.get=gtk_font_dialog_get_title org.gtk.Property.set=gtk_font_dialog_set_title)
|
||||
*
|
||||
* A title that may be shown on the font chooser
|
||||
* dialog that is presented by [function@Gtk.FontDialog.choose_font].
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
properties[PROP_TITLE] =
|
||||
g_param_spec_string ("title", NULL, NULL,
|
||||
NULL,
|
||||
G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS|G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GtkFontDialog:modal: (attributes org.gtk.Property.get=gtk_font_dialog_get_modal org.gtk.Property.set=gtk_font_dialog_set_modal)
|
||||
*
|
||||
* Whether the font chooser dialog is modal.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
properties[PROP_MODAL] =
|
||||
g_param_spec_boolean ("modal", NULL, NULL,
|
||||
TRUE,
|
||||
G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS|G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
|
||||
/**
|
||||
* GtkFontDialog:level: (attributes org.gtk.Property.get=gtk_font_dialog_get_level org.gtk.Property.set=gtk_font_dialog_set_level)
|
||||
*
|
||||
* The level of granularity to offer for selecting fonts.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
properties[PROP_LEVEL] =
|
||||
g_param_spec_flags ("level", NULL, NULL,
|
||||
GTK_TYPE_FONT_CHOOSER_LEVEL,
|
||||
DEFAULT_LEVEL,
|
||||
G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS|G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GtkFontDialog:language: (attributes org.gtk.Property.get=gtk_font_dialog_get_language org.gtk.Property.set=gtk_font_dialog_set_language)
|
||||
*
|
||||
* The language for which the font features are selected.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
properties[PROP_LANGUAGE] =
|
||||
g_param_spec_boxed ("language", NULL, NULL,
|
||||
PANGO_TYPE_LANGUAGE,
|
||||
G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS|G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GtkFontDialog:fontmap: (attributes org.gtk.Property.get=gtk_font_dialog_get_fontmap org.gtk.Property.set=gtk_font_dialog_set_fontmap)
|
||||
*
|
||||
* Sets a custom font map to select fonts from.
|
||||
*
|
||||
* A custom font map can be used to present application-specific
|
||||
* fonts instead of or in addition to the normal system fonts.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
properties[PROP_FONTMAP] =
|
||||
g_param_spec_object ("fontmap", NULL, NULL,
|
||||
PANGO_TYPE_FONT_MAP,
|
||||
G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS|G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
g_object_class_install_properties (object_class, NUM_PROPERTIES, properties);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Constructor */
|
||||
|
||||
/**
|
||||
* gtk_font_dialog_new:
|
||||
*
|
||||
* Creates a new `GtkFontDialog` object.
|
||||
*
|
||||
* Returns: the new `GtkFontDialog`
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
GtkFontDialog *
|
||||
gtk_font_dialog_new (void)
|
||||
{
|
||||
return g_object_new (GTK_TYPE_FONT_DIALOG, NULL);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Getters and setters */
|
||||
|
||||
/**
|
||||
* gtk_font_dialog_get_title:
|
||||
* @self: a `GtkFontDialog`
|
||||
*
|
||||
* Returns the title that will be shown on the
|
||||
* font chooser dialog.
|
||||
*
|
||||
* Returns: the title
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
const char *
|
||||
gtk_font_dialog_get_title (GtkFontDialog *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_FONT_DIALOG (self), NULL);
|
||||
|
||||
return self->title;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_font_dialog_set_title:
|
||||
* @self: a `GtkFontDialog`
|
||||
* @title: the new title
|
||||
*
|
||||
* Sets the title that will be shown on the
|
||||
* font chooser dialog.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
void
|
||||
gtk_font_dialog_set_title (GtkFontDialog *self,
|
||||
const char *title)
|
||||
{
|
||||
char *new_title;
|
||||
|
||||
g_return_if_fail (GTK_IS_FONT_DIALOG (self));
|
||||
g_return_if_fail (title != NULL);
|
||||
|
||||
if (g_str_equal (self->title, title))
|
||||
return;
|
||||
|
||||
new_title = g_strdup (title);
|
||||
g_free (self->title);
|
||||
self->title = new_title;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_TITLE]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_font_dialog_get_modal:
|
||||
* @self: a `GtkFontDialog`
|
||||
*
|
||||
* Returns whether the font chooser dialog
|
||||
* blocks interaction with the parent window
|
||||
* while it is presented.
|
||||
*
|
||||
* Returns: `TRUE` if the font chooser dialog is modal
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
gboolean
|
||||
gtk_font_dialog_get_modal (GtkFontDialog *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_FONT_DIALOG (self), TRUE);
|
||||
|
||||
return self->modal;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_font_dialog_set_modal:
|
||||
* @self: a `GtkFontDialog`
|
||||
* @modal: the new value
|
||||
*
|
||||
* Sets whether the font chooser dialog
|
||||
* blocks interaction with the parent window
|
||||
* while it is presented.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
void
|
||||
gtk_font_dialog_set_modal (GtkFontDialog *self,
|
||||
gboolean modal)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_FONT_DIALOG (self));
|
||||
|
||||
if (self->modal == modal)
|
||||
return;
|
||||
|
||||
self->modal = modal;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_MODAL]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_font_dialog_get_level:
|
||||
* @self: a `GtkFontDialog`
|
||||
*
|
||||
* Returns the level of granularity for selecting fonts.
|
||||
*
|
||||
* Returns: the level of granularity
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
GtkFontChooserLevel
|
||||
gtk_font_dialog_get_level (GtkFontDialog *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_FONT_DIALOG (self), DEFAULT_LEVEL);
|
||||
|
||||
return self->level;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_font_dialog_set_level:
|
||||
* @self: a `GtkFontDialog`
|
||||
* @level: the new value
|
||||
*
|
||||
* Sets the level of granularity for selecting fonts.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
void
|
||||
gtk_font_dialog_set_level (GtkFontDialog *self,
|
||||
GtkFontChooserLevel level)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_FONT_DIALOG (self));
|
||||
|
||||
if (self->level == level)
|
||||
return;
|
||||
|
||||
self->level = level;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_LEVEL]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_font_dialog_get_language:
|
||||
* @self: a `GtkFontDialog`
|
||||
*
|
||||
* Returns the language for which font features are applied.
|
||||
*
|
||||
* Returns: (nullable): the language for font features
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
PangoLanguage *
|
||||
gtk_font_dialog_get_language (GtkFontDialog *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_FONT_DIALOG (self), NULL);
|
||||
|
||||
return self->language;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_font_dialog_set_language:
|
||||
* @self: a `GtkFontDialog`
|
||||
* @language: the language for font features
|
||||
*
|
||||
* Sets the language for which font features are applied.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
void
|
||||
gtk_font_dialog_set_language (GtkFontDialog *self,
|
||||
PangoLanguage *language)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_FONT_DIALOG (self));
|
||||
|
||||
if (self->language == language)
|
||||
return;
|
||||
|
||||
self->language = language;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_LANGUAGE]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_font_dialog_get_fontmap
|
||||
* @self: a `GtkFontDialog`
|
||||
*
|
||||
* Returns the fontmap from which fonts are selected,
|
||||
* or `NULL` for the default fontmap.
|
||||
*
|
||||
* Returns: (nullable) (transfer none): the fontmap
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
PangoFontMap *
|
||||
gtk_font_dialog_get_fontmap (GtkFontDialog *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_FONT_DIALOG (self), NULL);
|
||||
|
||||
return self->fontmap;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_font_dialog_set_fontmap:
|
||||
* @self: a `GtkFontDialog`
|
||||
* @fontmap: (nullable): the fontmap
|
||||
*
|
||||
* Sets the fontmap from which fonts are selected.
|
||||
*
|
||||
* If @fontmap is `NULL`, the default fontmap is used.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
void
|
||||
gtk_font_dialog_set_fontmap (GtkFontDialog *self,
|
||||
PangoFontMap *fontmap)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_FONT_DIALOG (self));
|
||||
|
||||
if (g_set_object (&self->fontmap, fontmap))
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FONTMAP]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_font_dialog_set_filter:
|
||||
* @self: a `GtkFontDialog`
|
||||
* @filter: (nullable): a `GtkFontFilterFunc`
|
||||
* @user_data: (closure): data to pass to @filter
|
||||
* @destroy: function to call to free @data when it is no longer needed
|
||||
*
|
||||
* Adds a filter function that decides which fonts to display
|
||||
* in the font chooser dialog.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
void
|
||||
gtk_font_dialog_set_filter (GtkFontDialog *self,
|
||||
GtkFontFilterFunc filter,
|
||||
gpointer filter_data,
|
||||
GDestroyNotify filter_data_destroy)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_FONT_DIALOG (self));
|
||||
|
||||
g_clear_pointer (&self->filter_data, self->filter_data_destroy);
|
||||
|
||||
self->filter = filter;
|
||||
self->filter_data = filter_data;
|
||||
self->filter_data_destroy = filter_data_destroy;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Async API */
|
||||
|
||||
static void response_cb (GTask *task,
|
||||
int response);
|
||||
|
||||
static void
|
||||
cancelled_cb (GCancellable *cancellable,
|
||||
GTask *task)
|
||||
{
|
||||
response_cb (task, GTK_RESPONSE_CANCEL);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PangoFontDescription *font_desc;
|
||||
char *font_features;
|
||||
|
||||
} FontResult;
|
||||
|
||||
static void
|
||||
response_cb (GTask *task,
|
||||
int response)
|
||||
{
|
||||
GCancellable *cancellable;
|
||||
|
||||
cancellable = g_task_get_cancellable (task);
|
||||
|
||||
if (cancellable)
|
||||
g_signal_handlers_disconnect_by_func (cancellable, cancelled_cb, task);
|
||||
|
||||
if (response == GTK_RESPONSE_OK)
|
||||
{
|
||||
GtkFontChooserDialog *window;
|
||||
FontResult font_result;
|
||||
|
||||
window = GTK_FONT_CHOOSER_DIALOG (g_task_get_task_data (task));
|
||||
|
||||
font_result.font_desc = gtk_font_chooser_get_font_desc (GTK_FONT_CHOOSER (window));
|
||||
font_result.font_features = gtk_font_chooser_get_font_features (GTK_FONT_CHOOSER (window));
|
||||
|
||||
g_task_return_pointer (task, &font_result, NULL);
|
||||
}
|
||||
else
|
||||
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_CANCELLED, "Cancelled");
|
||||
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static void
|
||||
dialog_response (GtkDialog *dialog,
|
||||
int response,
|
||||
GTask *task)
|
||||
{
|
||||
response_cb (task, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_font_dialog_choose_font:
|
||||
* @self: a `GtkFontDialog`
|
||||
* @parent: (nullable): the parent `GtkWindow`
|
||||
* @initial_font: (nullable): the font to select initially
|
||||
* @cancellable: (nullable): a `GCancellable` to cancel the operation
|
||||
* @callback: (scope async): a callback to call when the operation is complete
|
||||
* @user_data: (closure callback): data to pass to @callback
|
||||
*
|
||||
* This function initiates a font selection operation by
|
||||
* presenting a font chooser dialog to the user.
|
||||
*
|
||||
* The @callback will be called when the dialog is dismissed.
|
||||
* It should call [function@Gtk.FontDialog.choose_font_finish]
|
||||
* to obtain the result.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
void
|
||||
gtk_font_dialog_choose_font (GtkFontDialog *self,
|
||||
GtkWindow *parent,
|
||||
PangoFontDescription *initial_font,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkFontChooserDialog *window;
|
||||
GTask *task;
|
||||
|
||||
g_return_if_fail (GTK_IS_FONT_DIALOG (self));
|
||||
|
||||
window = GTK_FONT_CHOOSER_DIALOG (gtk_font_chooser_dialog_new (self->title, parent));
|
||||
gtk_font_chooser_set_level (GTK_FONT_CHOOSER (window), self->level);
|
||||
if (self->language)
|
||||
gtk_font_chooser_set_language (GTK_FONT_CHOOSER (window), pango_language_to_string (self->language));
|
||||
if (self->fontmap)
|
||||
gtk_font_chooser_set_font_map (GTK_FONT_CHOOSER (window), self->fontmap);
|
||||
if (initial_font)
|
||||
gtk_font_chooser_set_font_desc (GTK_FONT_CHOOSER (window), initial_font);
|
||||
if (self->filter)
|
||||
gtk_font_chooser_set_filter_func (GTK_FONT_CHOOSER (window),
|
||||
self->filter,
|
||||
self->filter_data,
|
||||
self->filter_data_destroy);
|
||||
|
||||
task = g_task_new (self, cancellable, callback, user_data);
|
||||
g_task_set_source_tag (task, gtk_font_dialog_choose_font);
|
||||
g_task_set_task_data (task, window, (GDestroyNotify) gtk_window_destroy);
|
||||
|
||||
if (cancellable)
|
||||
g_signal_connect (cancellable, "cancelled", G_CALLBACK (cancelled_cb), task);
|
||||
|
||||
g_signal_connect (window, "response", G_CALLBACK (dialog_response), task);
|
||||
|
||||
gtk_window_present (GTK_WINDOW (window));
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_font_dialog_choose_font_finish:
|
||||
* @self: a `GtkFontDialog`
|
||||
* @result: a `GAsyncResult`
|
||||
* @font_desc: (out caller-allocates): return location for font description
|
||||
* @font_features: (out caller-allocates): return location for font features
|
||||
* @error: return location for an error
|
||||
*
|
||||
* Finishes the [function@Gtk.FontDialog.choose_font] call and
|
||||
* returns the resulting font description and font features.
|
||||
*
|
||||
* Returns: `TRUE` if a font was selected. Otherwise,
|
||||
* `FALSE` is returned and @error is set
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
gboolean
|
||||
gtk_font_dialog_choose_font_finish (GtkFontDialog *self,
|
||||
GAsyncResult *result,
|
||||
PangoFontDescription **font_desc,
|
||||
char **font_features,
|
||||
GError **error)
|
||||
{
|
||||
FontResult *font_result;
|
||||
|
||||
font_result = g_task_propagate_pointer (G_TASK (result), error);
|
||||
if (font_result)
|
||||
{
|
||||
*font_desc = font_result->font_desc;
|
||||
*font_features = font_result->font_features;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* vim:set foldmethod=marker expandtab: */
|
97
gtk/gtkfontdialog.h
Normal file
97
gtk/gtkfontdialog.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/* GTK - The GIMP Toolkit
|
||||
*
|
||||
* Copyright (C) 2022 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gtk/gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <gtk/gtkwindow.h>
|
||||
#include <gtk/gtkfontchooser.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_FONT_DIALOG (gtk_font_dialog_get_type ())
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
G_DECLARE_FINAL_TYPE (GtkFontDialog, gtk_font_dialog, GTK, FONT_DIALOG, GObject)
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
GtkFontDialog * gtk_font_dialog_new (void);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
void gtk_font_dialog_set_title (GtkFontDialog *self,
|
||||
const char *title);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
gboolean gtk_font_dialog_get_modal (GtkFontDialog *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
void gtk_font_dialog_set_modal (GtkFontDialog *self,
|
||||
gboolean modal);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
const char * gtk_font_dialog_get_title (GtkFontDialog *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
void gtk_font_dialog_set_level (GtkFontDialog *self,
|
||||
GtkFontChooserLevel level);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
GtkFontChooserLevel
|
||||
gtk_font_dialog_get_level (GtkFontDialog *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
void gtk_font_dialog_set_language (GtkFontDialog *self,
|
||||
PangoLanguage *language);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
PangoLanguage * gtk_font_dialog_get_language (GtkFontDialog *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
PangoFontMap * gtk_font_dialog_get_fontmap (GtkFontDialog *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
void gtk_font_dialog_set_fontmap (GtkFontDialog *self,
|
||||
PangoFontMap *fontmap);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
void gtk_font_dialog_set_filter (GtkFontDialog *self,
|
||||
GtkFontFilterFunc filter,
|
||||
gpointer user_data,
|
||||
GDestroyNotify destroy);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
void gtk_font_dialog_choose_font (GtkFontDialog *self,
|
||||
GtkWindow *parent,
|
||||
PangoFontDescription *initial_font,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
gboolean gtk_font_dialog_choose_font_finish
|
||||
(GtkFontDialog *self,
|
||||
GAsyncResult *result,
|
||||
PangoFontDescription **font_desc,
|
||||
char **font_features,
|
||||
GError **error);
|
||||
|
||||
G_END_DECLS
|
778
gtk/gtkfontdialogbutton.c
Normal file
778
gtk/gtkfontdialogbutton.c
Normal file
@@ -0,0 +1,778 @@
|
||||
/*
|
||||
* GTK - The GIMP Toolkit
|
||||
* Copyright (C) 2022 Red Hat, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This Library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This Library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkfontdialogbutton.h"
|
||||
|
||||
#include "gtkbinlayout.h"
|
||||
#include "gtkbox.h"
|
||||
#include "gtkseparator.h"
|
||||
#include "gtkbutton.h"
|
||||
#include "gtklabel.h"
|
||||
#include <glib/gi18n-lib.h>
|
||||
#include "gtkmain.h"
|
||||
#include "gtkprivate.h"
|
||||
#include "gtkwidgetprivate.h"
|
||||
|
||||
|
||||
static void button_clicked (GtkFontDialogButton *self);
|
||||
|
||||
/**
|
||||
* GtkFontDialogButton:
|
||||
*
|
||||
* The `GtkFontDialogButton` is wrapped around a [class@Gtk.FontDialog]
|
||||
* and allows to open a font chooser dialog to change the font.
|
||||
*
|
||||
* 
|
||||
*
|
||||
* It is suitable widget for selecting a font in a preference dialog.
|
||||
*
|
||||
* # CSS nodes
|
||||
*
|
||||
* ```
|
||||
* fontbutton
|
||||
* ╰── button.font
|
||||
* ╰── [content]
|
||||
* ```
|
||||
*
|
||||
* `GtkFontDialogButton` has a single CSS node with name fontbutton which
|
||||
* contains a button node with the .font style class.
|
||||
*/
|
||||
|
||||
/* {{{ GObject implementation */
|
||||
|
||||
struct _GtkFontDialogButton
|
||||
{
|
||||
GtkWidget parent_instance;
|
||||
|
||||
GtkWidget *button;
|
||||
GtkWidget *font_label;
|
||||
GtkWidget *size_label;
|
||||
GtkWidget *font_size_box;
|
||||
|
||||
guint use_font : 1;
|
||||
guint use_size : 1;
|
||||
|
||||
GtkFontDialog *dialog;
|
||||
PangoFontDescription *font_desc;
|
||||
char *font_features;
|
||||
|
||||
PangoFontFamily *font_family;
|
||||
PangoFontFace *font_face;
|
||||
};
|
||||
|
||||
/* Properties */
|
||||
enum
|
||||
{
|
||||
PROP_DIALOG = 1,
|
||||
PROP_FONT_DESC,
|
||||
PROP_FONT_FEATURES,
|
||||
PROP_USE_FONT,
|
||||
PROP_USE_SIZE,
|
||||
NUM_PROPERTIES
|
||||
};
|
||||
|
||||
static GParamSpec *properties[NUM_PROPERTIES];
|
||||
|
||||
G_DEFINE_TYPE (GtkFontDialogButton, gtk_font_dialog_button, GTK_TYPE_WIDGET)
|
||||
|
||||
static void
|
||||
gtk_font_dialog_button_init (GtkFontDialogButton *self)
|
||||
{
|
||||
GtkWidget *box;
|
||||
PangoFontDescription *font_desc;
|
||||
|
||||
self->button = gtk_button_new ();
|
||||
g_signal_connect_swapped (self->button, "clicked", G_CALLBACK (button_clicked), self);
|
||||
self->font_label = gtk_label_new (_("Font"));
|
||||
gtk_widget_set_hexpand (self->font_label, TRUE);
|
||||
self->size_label = gtk_label_new ("14");
|
||||
self->font_size_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
||||
gtk_box_append (GTK_BOX (box), self->font_label);
|
||||
|
||||
gtk_box_append (GTK_BOX (self->font_size_box), gtk_separator_new (GTK_ORIENTATION_VERTICAL));
|
||||
gtk_box_append (GTK_BOX (self->font_size_box), self->size_label);
|
||||
gtk_box_append (GTK_BOX (box), self->font_size_box);
|
||||
|
||||
gtk_button_set_child (GTK_BUTTON (self->button), box);
|
||||
gtk_widget_set_parent (self->button, GTK_WIDGET (self));
|
||||
|
||||
self->use_font = FALSE;
|
||||
self->use_size = FALSE;
|
||||
|
||||
font_desc = pango_font_description_from_string ("Sans 12");
|
||||
gtk_font_dialog_button_set_font_desc (self, font_desc);
|
||||
pango_font_description_free (font_desc);
|
||||
|
||||
gtk_widget_add_css_class (self->button, "font");
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_font_dialog_button_set_property (GObject *object,
|
||||
unsigned int param_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkFontDialogButton *self = GTK_FONT_DIALOG_BUTTON (object);
|
||||
|
||||
switch (param_id)
|
||||
{
|
||||
case PROP_DIALOG:
|
||||
gtk_font_dialog_button_set_dialog (self, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
case PROP_FONT_DESC:
|
||||
gtk_font_dialog_button_set_font_desc (self, g_value_get_boxed (value));
|
||||
break;
|
||||
|
||||
case PROP_FONT_FEATURES:
|
||||
gtk_font_dialog_button_set_font_features (self, g_value_get_string (value));
|
||||
break;
|
||||
|
||||
case PROP_USE_FONT:
|
||||
gtk_font_dialog_button_set_use_font (self, g_value_get_boolean (value));
|
||||
break;
|
||||
|
||||
case PROP_USE_SIZE:
|
||||
gtk_font_dialog_button_set_use_size (self, g_value_get_boolean (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_font_dialog_button_get_property (GObject *object,
|
||||
unsigned int param_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkFontDialogButton *self = GTK_FONT_DIALOG_BUTTON (object);
|
||||
|
||||
switch (param_id)
|
||||
{
|
||||
case PROP_DIALOG:
|
||||
g_value_set_object (value, self->dialog);
|
||||
break;
|
||||
|
||||
case PROP_FONT_DESC:
|
||||
g_value_set_boxed (value, self->font_desc);
|
||||
break;
|
||||
|
||||
case PROP_FONT_FEATURES:
|
||||
g_value_set_string (value, self->font_features);
|
||||
break;
|
||||
|
||||
case PROP_USE_FONT:
|
||||
g_value_set_boolean (value, self->use_font);
|
||||
break;
|
||||
|
||||
case PROP_USE_SIZE:
|
||||
g_value_set_boolean (value, self->use_size);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_font_dialog_button_dispose (GObject *object)
|
||||
{
|
||||
GtkFontDialogButton *self = GTK_FONT_DIALOG_BUTTON (object);
|
||||
|
||||
g_clear_pointer (&self->button, gtk_widget_unparent);
|
||||
|
||||
G_OBJECT_CLASS (gtk_font_dialog_button_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_font_dialog_button_finalize (GObject *object)
|
||||
{
|
||||
GtkFontDialogButton *self = GTK_FONT_DIALOG_BUTTON (object);
|
||||
|
||||
g_clear_object (&self->dialog);
|
||||
pango_font_description_free (self->font_desc);
|
||||
g_clear_object (&self->font_family);
|
||||
g_clear_object (&self->font_face);
|
||||
g_free (self->font_features);
|
||||
|
||||
G_OBJECT_CLASS (gtk_font_dialog_button_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_font_dialog_button_class_init (GtkFontDialogButtonClass *class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
|
||||
|
||||
object_class->get_property = gtk_font_dialog_button_get_property;
|
||||
object_class->set_property = gtk_font_dialog_button_set_property;
|
||||
object_class->dispose = gtk_font_dialog_button_dispose;
|
||||
object_class->finalize = gtk_font_dialog_button_finalize;
|
||||
|
||||
widget_class->grab_focus = gtk_widget_grab_focus_child;
|
||||
widget_class->focus = gtk_widget_focus_child;
|
||||
|
||||
/**
|
||||
* GtkFontDialogButton:dialog: (attributes org.gtk.Property.get=gtk_font_dialog_button_get_dialog org.gtk.Property.set=gtk_font_dialog_button_set_dialog)
|
||||
*
|
||||
* The `GtkFontDialog` that contains parameters for
|
||||
* the font chooser dialog.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
properties[PROP_DIALOG] =
|
||||
g_param_spec_object ("dialog", NULL, NULL,
|
||||
GTK_TYPE_FONT_DIALOG,
|
||||
G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS|G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GtkFontDialogButton:font-desc: (attributes org.gtk.Property.get=gtk_font_dialog_button_get_font_desc org.gtk.Property.set=gtk_font_dialog_button_set_font_desc)
|
||||
*
|
||||
* The selected font.
|
||||
*
|
||||
* This property can be set to give the button its initial
|
||||
* font, and it will be updated to reflect the users choice
|
||||
* in the font chooser dialog.
|
||||
*
|
||||
* Listen to `notify::font-desc` to get informed about changes
|
||||
* to the buttons font.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
properties[PROP_FONT_DESC] =
|
||||
g_param_spec_boxed ("font-desc", NULL, NULL,
|
||||
PANGO_TYPE_FONT_DESCRIPTION,
|
||||
G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS|G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GtkFontDialogButton:font-features: (attributes org.gtk.Property.get=gtk_font_dialog_button_get_font_features org.gtk.Property.set=gtk_font_dialog_button_set_font_features)
|
||||
*
|
||||
* The selected font features.
|
||||
*
|
||||
* This property will be updated to reflect the users choice
|
||||
* in the font chooser dialog.
|
||||
*
|
||||
* Listen to `notify::font-features` to get informed about changes
|
||||
* to the buttons font features.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
properties[PROP_FONT_FEATURES] =
|
||||
g_param_spec_string ("font-features", NULL, NULL,
|
||||
NULL,
|
||||
G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS|G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GtkFontDialogButton:use-font: (attributes org.gtk.Property.get=gtk_font_dialog_button_get_use_font org.gtk.Property.set=gtk_font_dialog_button_set_use_font)
|
||||
*
|
||||
* Whether the buttons label will be drawn in the selected font.
|
||||
*/
|
||||
properties[PROP_USE_FONT] =
|
||||
g_param_spec_boolean ("use-font", NULL, NULL,
|
||||
FALSE,
|
||||
GTK_PARAM_READWRITE|G_PARAM_STATIC_STRINGS|G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GtkFontDialogButton:use-size: (attributes org.gtk.Property.get=gtk_font_dialog_button_get_use_size org.gtk.Property.set=gtk_font_dialog_button_set_use_size)
|
||||
*
|
||||
* Whether the buttons label will use the selected font size.
|
||||
*/
|
||||
properties[PROP_USE_SIZE] =
|
||||
g_param_spec_boolean ("use-size", NULL, NULL,
|
||||
FALSE,
|
||||
GTK_PARAM_READWRITE|G_PARAM_STATIC_STRINGS|G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
g_object_class_install_properties (object_class, NUM_PROPERTIES, properties);
|
||||
|
||||
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
|
||||
gtk_widget_class_set_css_name (widget_class, "fontbutton");
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Private API, callbacks */
|
||||
|
||||
static void
|
||||
font_chosen (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer data)
|
||||
{
|
||||
GtkFontDialogButton *self = data;
|
||||
PangoFontDescription *desc;
|
||||
char *features;
|
||||
GError *error = NULL;
|
||||
|
||||
if (gtk_font_dialog_choose_font_finish (self->dialog, result, &desc, &features, &error))
|
||||
{
|
||||
gtk_font_dialog_button_set_font_desc (self, desc);
|
||||
gtk_font_dialog_button_set_font_features (self, features);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_print ("%s\n", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
button_clicked (GtkFontDialogButton *self)
|
||||
{
|
||||
GtkRoot *root = gtk_widget_get_root (GTK_WIDGET (self));
|
||||
GtkWindow *parent = NULL;
|
||||
|
||||
if (GTK_IS_WINDOW (root))
|
||||
parent = GTK_WINDOW (root);
|
||||
|
||||
gtk_font_dialog_choose_font (self->dialog, parent, self->font_desc,
|
||||
NULL, font_chosen, self);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
font_description_style_equal (const PangoFontDescription *a,
|
||||
const PangoFontDescription *b)
|
||||
{
|
||||
return (pango_font_description_get_weight (a) == pango_font_description_get_weight (b) &&
|
||||
pango_font_description_get_style (a) == pango_font_description_get_style (b) &&
|
||||
pango_font_description_get_stretch (a) == pango_font_description_get_stretch (b) &&
|
||||
pango_font_description_get_variant (a) == pango_font_description_get_variant (b));
|
||||
}
|
||||
|
||||
static void
|
||||
update_font_data (GtkFontDialogButton *self)
|
||||
{
|
||||
PangoFontMap *fontmap = NULL;
|
||||
const char *family_name;
|
||||
|
||||
g_assert (self->font_desc != NULL);
|
||||
|
||||
g_clear_object (&self->font_family);
|
||||
g_clear_object (&self->font_face);
|
||||
|
||||
family_name = pango_font_description_get_family (self->font_desc);
|
||||
if (family_name == NULL)
|
||||
return;
|
||||
|
||||
if (self->dialog)
|
||||
fontmap = gtk_font_dialog_get_fontmap (self->dialog);
|
||||
if (!fontmap)
|
||||
fontmap = pango_cairo_font_map_get_default ();
|
||||
|
||||
for (unsigned int i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (fontmap)); i++)
|
||||
{
|
||||
PangoFontFamily *family = g_list_model_get_item (G_LIST_MODEL (fontmap), i);
|
||||
const char *name = pango_font_family_get_name (family);
|
||||
g_object_unref (family);
|
||||
|
||||
if (g_ascii_strcasecmp (name, family_name) == 0)
|
||||
{
|
||||
g_set_object (&self->font_family, family);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (self->font_family)); i++)
|
||||
{
|
||||
PangoFontFace *face = g_list_model_get_item (G_LIST_MODEL (self->font_family), i);
|
||||
PangoFontDescription *tmp_desc = pango_font_face_describe (face);
|
||||
g_object_unref (face);
|
||||
|
||||
if (font_description_style_equal (tmp_desc, self->font_desc))
|
||||
{
|
||||
g_set_object (&self->font_face, face);
|
||||
pango_font_description_free (tmp_desc);
|
||||
break;
|
||||
}
|
||||
else
|
||||
pango_font_description_free (tmp_desc);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
update_font_info (GtkFontDialogButton *self)
|
||||
{
|
||||
const char *fam_name;
|
||||
const char *face_name;
|
||||
char *family_style;
|
||||
GtkFontChooserLevel level;
|
||||
|
||||
if (self->font_family)
|
||||
fam_name = pango_font_family_get_name (self->font_family);
|
||||
else
|
||||
fam_name = C_("font", "None");
|
||||
if (self->font_face)
|
||||
face_name = pango_font_face_get_face_name (self->font_face);
|
||||
else
|
||||
face_name = "";
|
||||
|
||||
if (self->dialog)
|
||||
level = gtk_font_dialog_get_level (self->dialog);
|
||||
else
|
||||
level = GTK_FONT_CHOOSER_LEVEL_STYLE|GTK_FONT_CHOOSER_LEVEL_SIZE;
|
||||
|
||||
if ((level & GTK_FONT_CHOOSER_LEVEL_STYLE) != 0)
|
||||
family_style = g_strconcat (fam_name, " ", face_name, NULL);
|
||||
else
|
||||
family_style = g_strdup (fam_name);
|
||||
|
||||
gtk_label_set_text (GTK_LABEL (self->font_label), family_style);
|
||||
g_free (family_style);
|
||||
|
||||
if ((level & GTK_FONT_CHOOSER_LEVEL_SIZE) != 0)
|
||||
{
|
||||
/* mirror Pango, which doesn't translate this either */
|
||||
char *size = g_strdup_printf ("%2.4g%s",
|
||||
pango_font_description_get_size (self->font_desc) / (double)PANGO_SCALE,
|
||||
pango_font_description_get_size_is_absolute (self->font_desc) ? "px" : "");
|
||||
|
||||
gtk_label_set_text (GTK_LABEL (self->size_label), size);
|
||||
|
||||
g_free (size);
|
||||
|
||||
gtk_widget_show (self->font_size_box);
|
||||
}
|
||||
else
|
||||
gtk_widget_hide (self->font_size_box);
|
||||
}
|
||||
|
||||
static void
|
||||
apply_use_font (GtkFontDialogButton *self)
|
||||
{
|
||||
if (!self->use_font)
|
||||
gtk_label_set_attributes (GTK_LABEL (self->font_label), NULL);
|
||||
else
|
||||
{
|
||||
PangoFontDescription *desc;
|
||||
PangoAttrList *attrs;
|
||||
PangoLanguage *language = NULL;
|
||||
|
||||
desc = pango_font_description_copy (self->font_desc);
|
||||
|
||||
if (!self->use_size)
|
||||
pango_font_description_unset_fields (desc, PANGO_FONT_MASK_SIZE);
|
||||
|
||||
attrs = pango_attr_list_new ();
|
||||
|
||||
/* Prevent font fallback */
|
||||
pango_attr_list_insert (attrs, pango_attr_fallback_new (FALSE));
|
||||
|
||||
/* Force current font and features */
|
||||
pango_attr_list_insert (attrs, pango_attr_font_desc_new (desc));
|
||||
if (self->font_features)
|
||||
pango_attr_list_insert (attrs, pango_attr_font_features_new (self->font_features));
|
||||
if (self->dialog)
|
||||
language = gtk_font_dialog_get_language (self->dialog);
|
||||
if (language)
|
||||
pango_attr_list_insert (attrs, pango_attr_language_new (language));
|
||||
|
||||
gtk_label_set_attributes (GTK_LABEL (self->font_label), attrs);
|
||||
|
||||
pango_attr_list_unref (attrs);
|
||||
pango_font_description_free (desc);
|
||||
}
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Public API */
|
||||
/* {{{ Constructor */
|
||||
|
||||
/**
|
||||
* gtk_font_dialog_button_new:
|
||||
* @dialog: (nullable) (transfer full): the `GtkFontDialog` to use
|
||||
*
|
||||
* Creates a new `GtkFontDialogButton` with the
|
||||
* given `GtkFontDialog`.
|
||||
*
|
||||
* You can pass `NULL` to this function and set a `GtkFontDialog`
|
||||
* later. The button will be insensitive until that happens.
|
||||
*
|
||||
* Returns: the new `GtkFontDialogButton`
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
GtkWidget *
|
||||
gtk_font_dialog_button_new (GtkFontDialog *dialog)
|
||||
{
|
||||
GtkWidget *self;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_FONT_DIALOG (dialog), NULL);
|
||||
|
||||
self = g_object_new (GTK_TYPE_FONT_DIALOG_BUTTON,
|
||||
"dialog", dialog,
|
||||
NULL);
|
||||
|
||||
g_clear_object (&dialog);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Setters and Getters */
|
||||
|
||||
/**
|
||||
* gtk_font_dialog_button_set_dialog:
|
||||
* @self: a `GtkFontDialogButton`
|
||||
* @dialog: the new `GtkFontDialog`
|
||||
*
|
||||
* Sets a `GtkFontDialog` object to use for
|
||||
* creating the font chooser dialog that is
|
||||
* presented when the user clicks the button.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
void
|
||||
gtk_font_dialog_button_set_dialog (GtkFontDialogButton *self,
|
||||
GtkFontDialog *dialog)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_FONT_DIALOG_BUTTON (self));
|
||||
g_return_if_fail (dialog == NULL || GTK_IS_FONT_DIALOG (dialog));
|
||||
|
||||
if (!g_set_object (&self->dialog, dialog))
|
||||
return;
|
||||
|
||||
gtk_widget_set_sensitive (self->button, dialog != NULL);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DIALOG]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_font_dialog_button_get_dialog:
|
||||
* @self: a `GtkFontDialogButton`
|
||||
*
|
||||
* Returns the `GtkFontDialog` of @self.
|
||||
*
|
||||
* Returns: (nullable) (transfer none): the `GtkFontDialog`
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
GtkFontDialog *
|
||||
gtk_font_dialog_button_get_dialog (GtkFontDialogButton *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_FONT_DIALOG_BUTTON (self), NULL);
|
||||
|
||||
return self->dialog;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_font_dialog_button_set_font_desc:
|
||||
* @self: a `GtkFontDialogButton`
|
||||
* @font_desc: the new font
|
||||
*
|
||||
* Sets the font of the button.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
void
|
||||
gtk_font_dialog_button_set_font_desc (GtkFontDialogButton *self,
|
||||
PangoFontDescription *font_desc)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_FONT_DIALOG_BUTTON (self));
|
||||
g_return_if_fail (font_desc != NULL);
|
||||
|
||||
if (self->font_desc == font_desc ||
|
||||
(self->font_desc && font_desc &&
|
||||
pango_font_description_equal (self->font_desc, font_desc)))
|
||||
return;
|
||||
|
||||
if (self->font_desc)
|
||||
pango_font_description_free (self->font_desc);
|
||||
|
||||
self->font_desc = pango_font_description_copy (font_desc);
|
||||
|
||||
update_font_data (self);
|
||||
update_font_info (self);
|
||||
apply_use_font (self);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FONT_DESC]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_font_dialog_button_get_font_desc:
|
||||
* @self: a `GtkFontDialogButton`
|
||||
*
|
||||
* Returns the font of the button.
|
||||
*
|
||||
* This function is what should be used to obtain
|
||||
* the font that was choosen by the user. To get
|
||||
* informed about changes, listen to "notify::font-desc".
|
||||
*
|
||||
* Returns: (transfer none) (nullable): the font
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
PangoFontDescription *
|
||||
gtk_font_dialog_button_get_font_desc (GtkFontDialogButton *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_FONT_DIALOG_BUTTON (self), NULL);
|
||||
|
||||
return self->font_desc;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_font_dialog_button_set_font_features:
|
||||
* @self: a `GtkFontDialogButton`
|
||||
* @font_features: (nullable): the font features
|
||||
*
|
||||
* Sets the font features of the button.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
void
|
||||
gtk_font_dialog_button_set_font_features (GtkFontDialogButton *self,
|
||||
const char *font_features)
|
||||
{
|
||||
char *new_features;
|
||||
|
||||
g_return_if_fail (GTK_IS_FONT_DIALOG_BUTTON (self));
|
||||
|
||||
if (g_strcmp0 (self->font_features, font_features) == 0)
|
||||
return;
|
||||
|
||||
new_features = g_strdup (font_features);
|
||||
g_free (self->font_features);
|
||||
self->font_features = new_features;
|
||||
|
||||
apply_use_font (self);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FONT_FEATURES]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_font_dialog_button_get_font_features:
|
||||
* @self: a `GtkFontDialogButton`
|
||||
*
|
||||
* Returns the font features of the button.
|
||||
*
|
||||
* This function is what should be used to obtain
|
||||
* the font features that were choosen by the user.
|
||||
* To get informed about changes, listen to
|
||||
* "notify::font-features".
|
||||
*
|
||||
* Returns: (transfer none) (nullable): the font features
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
const char *
|
||||
gtk_font_dialog_button_get_font_features (GtkFontDialogButton *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_FONT_DIALOG_BUTTON (self), NULL);
|
||||
|
||||
return self->font_features;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_font_dialog_button_set_use_font:
|
||||
* @self: a `GtkFontDialogButton`
|
||||
* @use_font: If `TRUE`, font name will be written using
|
||||
* the chosen font
|
||||
*
|
||||
* If @use_font is `TRUE`, the font name will be written
|
||||
* using the selected font.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
void
|
||||
gtk_font_dialog_button_set_use_font (GtkFontDialogButton *self,
|
||||
gboolean use_font)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_FONT_DIALOG_BUTTON (self));
|
||||
|
||||
if (self->use_font == use_font)
|
||||
return;
|
||||
|
||||
self->use_font = use_font;
|
||||
|
||||
apply_use_font (self);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_USE_FONT]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_font_dialog_button_get_use_font:
|
||||
* @self: a `GtkFontDialogButton`
|
||||
*
|
||||
* Returns whether the selected font is used in the label.
|
||||
*
|
||||
* Returns: whether the selected font is used in the label
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
gboolean
|
||||
gtk_font_dialog_button_get_use_font (GtkFontDialogButton *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_FONT_DIALOG_BUTTON (self), FALSE);
|
||||
|
||||
return self->use_font;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_font_dialog_button_set_use_size:
|
||||
* @self: a `GtkFontDialogButton`
|
||||
* @use_size: If `TRUE`, font name will be written using
|
||||
* the chosen font size
|
||||
*
|
||||
* If @use_size is `TRUE`, the font name will be written
|
||||
* using the selected font size.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
void
|
||||
gtk_font_dialog_button_set_use_size (GtkFontDialogButton *self,
|
||||
gboolean use_size)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_FONT_DIALOG_BUTTON (self));
|
||||
|
||||
if (self->use_size == use_size)
|
||||
return;
|
||||
|
||||
self->use_size = use_size;
|
||||
|
||||
apply_use_font (self);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_USE_SIZE]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_font_dialog_button_get_use_size:
|
||||
* @self: a `GtkFontDialogButton`
|
||||
*
|
||||
* Returns whether the selected font size is used in the label.
|
||||
*
|
||||
* Returns: whether the selected font size is used in the label
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
gboolean
|
||||
gtk_font_dialog_button_get_use_size (GtkFontDialogButton *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_FONT_DIALOG_BUTTON (self), FALSE);
|
||||
|
||||
return self->use_size;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* }}} */
|
||||
|
||||
/* vim:set foldmethod=marker expandtab: */
|
76
gtk/gtkfontdialogbutton.h
Normal file
76
gtk/gtkfontdialogbutton.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* GTK - The GIMP Toolkit
|
||||
* Copyright (C) 2022 Red Hat, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This Library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This Library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gtk/gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gtk/gtkbutton.h>
|
||||
#include <gtk/gtkfontdialog.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_FONT_DIALOG_BUTTON (gtk_font_dialog_button_get_type ())
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
G_DECLARE_FINAL_TYPE (GtkFontDialogButton, gtk_font_dialog_button, GTK, FONT_DIALOG_BUTTON, GtkWidget)
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
GtkWidget * gtk_font_dialog_button_new (GtkFontDialog *dialog);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
void gtk_font_dialog_button_set_dialog (GtkFontDialogButton *self,
|
||||
GtkFontDialog *dialog);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
GtkFontDialog * gtk_font_dialog_button_get_dialog (GtkFontDialogButton *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
void gtk_font_dialog_button_set_font_desc (GtkFontDialogButton *self,
|
||||
PangoFontDescription *font_desc);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
PangoFontDescription *
|
||||
gtk_font_dialog_button_get_font_desc (GtkFontDialogButton *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
void gtk_font_dialog_button_set_font_features
|
||||
(GtkFontDialogButton *self,
|
||||
const char *font_features);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
const char * gtk_font_dialog_button_get_font_features (GtkFontDialogButton *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
void gtk_font_dialog_button_set_use_font (GtkFontDialogButton *self,
|
||||
gboolean use_font);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
gboolean gtk_font_dialog_button_get_use_font (GtkFontDialogButton *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
void gtk_font_dialog_button_set_use_size (GtkFontDialogButton *self,
|
||||
gboolean use_size);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
gboolean gtk_font_dialog_button_get_use_size (GtkFontDialogButton *self);
|
||||
|
||||
G_END_DECLS
|
715
gtk/gtkinfodialog.c
Normal file
715
gtk/gtkinfodialog.c
Normal file
@@ -0,0 +1,715 @@
|
||||
/*
|
||||
* GTK - The GIMP Toolkit
|
||||
* Copyright (C) 2022 Red Hat, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This Library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This Library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkinfodialog.h"
|
||||
|
||||
#include "gtkbutton.h"
|
||||
#include "gtkmessagedialog.h"
|
||||
#include <glib/gi18n-lib.h>
|
||||
|
||||
/**
|
||||
* GtkInfoDialog:
|
||||
*
|
||||
* A `GtkInfoDialog` object collects the arguments that
|
||||
* are needed to present a info chooser dialog to the
|
||||
* user, such as a title for the dialog and whether it
|
||||
* should be modal.
|
||||
*
|
||||
* The dialog is shown with the [function@Gtk.InfoDialog.present]
|
||||
* function. This API follows the GIO async pattern, and the
|
||||
* result can be obtained by calling
|
||||
* [function@Gtk.InfoDialog.present_finish].
|
||||
*
|
||||
* `GtkInfoDialog was added in GTK 4.10.
|
||||
*/
|
||||
|
||||
/* {{{ GObject implementation */
|
||||
|
||||
struct _GtkInfoDialog
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
char *heading;
|
||||
char *body;
|
||||
char **buttons;
|
||||
|
||||
unsigned int modal : 1;
|
||||
unsigned int heading_use_markup: 1;
|
||||
unsigned int body_use_markup: 1;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_MODAL = 1,
|
||||
PROP_HEADING,
|
||||
PROP_HEADING_USE_MARKUP,
|
||||
PROP_BODY,
|
||||
PROP_BODY_USE_MARKUP,
|
||||
PROP_BUTTONS,
|
||||
|
||||
NUM_PROPERTIES
|
||||
};
|
||||
|
||||
static GParamSpec *properties[NUM_PROPERTIES];
|
||||
|
||||
G_DEFINE_TYPE (GtkInfoDialog, gtk_info_dialog, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
gtk_info_dialog_init (GtkInfoDialog *self)
|
||||
{
|
||||
self->modal = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_info_dialog_finalize (GObject *object)
|
||||
{
|
||||
GtkInfoDialog *self = GTK_INFO_DIALOG (object);
|
||||
|
||||
g_free (self->heading);
|
||||
g_free (self->body);
|
||||
g_strfreev (self->buttons);
|
||||
|
||||
G_OBJECT_CLASS (gtk_info_dialog_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_info_dialog_get_property (GObject *object,
|
||||
unsigned int property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkInfoDialog *self = GTK_INFO_DIALOG (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_MODAL:
|
||||
g_value_set_boolean (value, self->modal);
|
||||
break;
|
||||
|
||||
case PROP_HEADING:
|
||||
g_value_set_string (value, self->heading);
|
||||
break;
|
||||
|
||||
case PROP_HEADING_USE_MARKUP:
|
||||
g_value_set_boolean (value, self->heading_use_markup);
|
||||
break;
|
||||
|
||||
case PROP_BODY:
|
||||
g_value_set_string (value, self->body);
|
||||
break;
|
||||
|
||||
case PROP_BODY_USE_MARKUP:
|
||||
g_value_set_boolean (value, self->body_use_markup);
|
||||
break;
|
||||
|
||||
case PROP_BUTTONS:
|
||||
g_value_set_boxed (value, self->buttons);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_info_dialog_set_property (GObject *object,
|
||||
unsigned int prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkInfoDialog *self = GTK_INFO_DIALOG (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_MODAL:
|
||||
gtk_info_dialog_set_modal (self, g_value_get_boolean (value));
|
||||
break;
|
||||
|
||||
case PROP_HEADING:
|
||||
gtk_info_dialog_set_heading (self, g_value_get_string (value));
|
||||
break;
|
||||
|
||||
case PROP_HEADING_USE_MARKUP:
|
||||
gtk_info_dialog_set_heading_use_markup (self, g_value_get_boolean (value));
|
||||
break;
|
||||
|
||||
case PROP_BODY:
|
||||
gtk_info_dialog_set_body (self, g_value_get_string (value));
|
||||
break;
|
||||
|
||||
case PROP_BODY_USE_MARKUP:
|
||||
gtk_info_dialog_set_body_use_markup (self, g_value_get_boolean (value));
|
||||
break;
|
||||
|
||||
case PROP_BUTTONS:
|
||||
gtk_info_dialog_set_buttons (self, g_value_get_boxed (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_info_dialog_class_init (GtkInfoDialogClass *class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
|
||||
object_class->finalize = gtk_info_dialog_finalize;
|
||||
object_class->get_property = gtk_info_dialog_get_property;
|
||||
object_class->set_property = gtk_info_dialog_set_property;
|
||||
|
||||
/**
|
||||
* GtkInfoDialog:modal: (attributes org.gtk.Property.get=gtk_info_dialog_get_modal org.gtk.Property.set=gtk_color_dialog_set_modal)
|
||||
*
|
||||
* Whether the info chooser dialog is modal.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
properties[PROP_MODAL] =
|
||||
g_param_spec_boolean ("modal", NULL, NULL,
|
||||
TRUE,
|
||||
G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS|G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GtkInfoDialog:heading: (attributes org.gtk.Property.get=gtk_info_dialog_get_heading org.gtk.Property.set=gtk_color_dialog_set_heading)
|
||||
*
|
||||
* The heading for the dialog that is presented
|
||||
* by [function@Gtk.InfoDialog.present].
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
properties[PROP_HEADING] =
|
||||
g_param_spec_string ("heading", NULL, NULL,
|
||||
NULL,
|
||||
G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS|G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GtkInfoDialog:heading-use-markup: (attributes org.gtk.Property.get=gtk_info_dialog_get_heading_use_markup org.gtk.Property.set=gtk_color_dialog_set_heading_use_markup)
|
||||
*
|
||||
* Whether the heading uses markup.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
properties[PROP_HEADING_USE_MARKUP] =
|
||||
g_param_spec_boolean ("heading-use-markup", NULL, NULL,
|
||||
FALSE,
|
||||
G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS|G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GtkInfoDialog:body: (attributes org.gtk.Property.get=gtk_info_dialog_get_body org.gtk.Property.set=gtk_color_dialog_set_body)
|
||||
*
|
||||
* The body text for the dialog that is presented
|
||||
* by [function@Gtk.InfoDialog.present].
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
properties[PROP_BODY] =
|
||||
g_param_spec_string ("body", NULL, NULL,
|
||||
NULL,
|
||||
G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS|G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GtkInfoDialog:body-use-markup: (attributes org.gtk.Property.get=gtk_info_dialog_get_body_use_markup org.gtk.Property.set=gtk_color_dialog_set_body_use_markup)
|
||||
*
|
||||
* Whether the body text uses markup.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
properties[PROP_BODY_USE_MARKUP] =
|
||||
g_param_spec_boolean ("body-use-markup", NULL, NULL,
|
||||
FALSE,
|
||||
G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS|G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GtkInfoDialog:buttons: (attributes org.gtk.Property.get=gtk_info_dialog_get_buttons org.gtk.Property.set=gtk_color_dialog_set_buttons)
|
||||
*
|
||||
* The labels for buttons to show in the dialog that is presented
|
||||
* by [function@Gtk.InfoDialog.present].
|
||||
*
|
||||
* The labels should be translated and may contain a _ to indicate
|
||||
* mnemonic characters.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
properties[PROP_BUTTONS] =
|
||||
g_param_spec_boxed ("buttons", NULL, NULL,
|
||||
G_TYPE_STRV,
|
||||
G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS|G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
g_object_class_install_properties (object_class, NUM_PROPERTIES, properties);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Constructor */
|
||||
|
||||
/**
|
||||
* gtk_info_dialog_new:
|
||||
*
|
||||
* Creates a new `GtkInfoDialog` object.
|
||||
*
|
||||
* Returns: the new `GtkInfoDialog`
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
GtkInfoDialog *
|
||||
gtk_info_dialog_new (void)
|
||||
{
|
||||
return g_object_new (GTK_TYPE_INFO_DIALOG, NULL);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Getters and setters */
|
||||
|
||||
/**
|
||||
* gtk_info_dialog_get_modal:
|
||||
* @self: a `GtkInfoDialog`
|
||||
*
|
||||
* Returns whether the info chooser dialog
|
||||
* blocks interaction with the parent window
|
||||
* while it is presented.
|
||||
*
|
||||
* Returns: `TRUE` if the info chooser dialog is modal
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
gboolean
|
||||
gtk_info_dialog_get_modal (GtkInfoDialog *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_INFO_DIALOG (self), TRUE);
|
||||
|
||||
return self->modal;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_info_dialog_set_modal:
|
||||
* @self: a `GtkInfoDialog`
|
||||
* @modal: the new value
|
||||
*
|
||||
* Sets whether the info chooser dialog
|
||||
* blocks interaction with the parent window
|
||||
* while it is presented.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
void
|
||||
gtk_info_dialog_set_modal (GtkInfoDialog *self,
|
||||
gboolean modal)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_INFO_DIALOG (self));
|
||||
|
||||
if (self->modal == modal)
|
||||
return;
|
||||
|
||||
self->modal = modal;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_MODAL]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_info_dialog_get_heading:
|
||||
* @self: a `GtkInfoDialog`
|
||||
*
|
||||
* Returns the heading that will be shown in the
|
||||
* info dialog.
|
||||
*
|
||||
* Returns: the heading
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
const char *
|
||||
gtk_info_dialog_get_heading (GtkInfoDialog *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_INFO_DIALOG (self), NULL);
|
||||
|
||||
return self->heading;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_info_dialog_set_heading:
|
||||
* @self: a `GtkInfoDialog`
|
||||
* @text: the new heading
|
||||
*
|
||||
* Sets the heading that will be shown in the
|
||||
* info dialog.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
void
|
||||
gtk_info_dialog_set_heading (GtkInfoDialog *self,
|
||||
const char *text)
|
||||
{
|
||||
char *new_text;
|
||||
|
||||
g_return_if_fail (GTK_IS_INFO_DIALOG (self));
|
||||
g_return_if_fail (text != NULL);
|
||||
|
||||
if (g_strcmp0 (self->heading, text) == 0)
|
||||
return;
|
||||
|
||||
new_text = g_strdup (text);
|
||||
g_free (self->heading);
|
||||
self->heading = new_text;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_HEADING]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_info_dialog_get_heading_use_markup:
|
||||
* @self: a `GtkInfoDialog`
|
||||
*
|
||||
* Returns whether the heading uses markup.
|
||||
*
|
||||
* Returns: `TRUE` if the heading uses markup
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
gboolean
|
||||
gtk_info_dialog_get_heading_use_markup (GtkInfoDialog *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_INFO_DIALOG (self), FALSE);
|
||||
|
||||
return self->heading_use_markup;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_info_dialog_set_heading_use_markup:
|
||||
* @self: a `GtkInfoDialog`
|
||||
* @use_markup: the new value
|
||||
*
|
||||
* Sets whether the heading uses markup.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
void
|
||||
gtk_info_dialog_set_heading_use_markup (GtkInfoDialog *self,
|
||||
gboolean use_markup)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_INFO_DIALOG (self));
|
||||
|
||||
if (self->heading_use_markup == use_markup)
|
||||
return;
|
||||
|
||||
self->heading_use_markup = use_markup;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_HEADING_USE_MARKUP]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_info_dialog_get_body:
|
||||
* @self: a `GtkInfoDialog`
|
||||
*
|
||||
* Returns the body text that will be shown
|
||||
* in the info dialog.
|
||||
*
|
||||
* Returns: the body text
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
const char *
|
||||
gtk_info_dialog_get_body (GtkInfoDialog *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_INFO_DIALOG (self), NULL);
|
||||
|
||||
return self->body;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_info_dialog_set_body:
|
||||
* @self: a `GtkInfoDialog`
|
||||
* @text: the new text
|
||||
*
|
||||
* Sets the body text that will be shown
|
||||
* in the info dialog.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
void
|
||||
gtk_info_dialog_set_body (GtkInfoDialog *self,
|
||||
const char *text)
|
||||
{
|
||||
char *new_text;
|
||||
|
||||
g_return_if_fail (GTK_IS_INFO_DIALOG (self));
|
||||
g_return_if_fail (text != NULL);
|
||||
|
||||
if (g_strcmp0 (self->body, text) == 0)
|
||||
return;
|
||||
|
||||
new_text = g_strdup (text);
|
||||
g_free (self->body);
|
||||
self->body = new_text;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_BODY]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_info_dialog_get_body_use_markup:
|
||||
* @self: a `GtkInfoDialog`
|
||||
*
|
||||
* Returns whether the body text uses markup.
|
||||
*
|
||||
* Returns: `TRUE` if body text uses markup
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
gboolean
|
||||
gtk_info_dialog_get_body_use_markup (GtkInfoDialog *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_INFO_DIALOG (self), FALSE);
|
||||
|
||||
return self->body_use_markup;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_info_dialog_set_body_use_markup:
|
||||
* @self: a `GtkInfoDialog`
|
||||
* @use_markup: the new value
|
||||
*
|
||||
* Sets whether the body text uses markup.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
void
|
||||
gtk_info_dialog_set_body_use_markup (GtkInfoDialog *self,
|
||||
gboolean use_markup)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_INFO_DIALOG (self));
|
||||
|
||||
if (self->body_use_markup == use_markup)
|
||||
return;
|
||||
|
||||
self->body_use_markup = use_markup;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_BODY_USE_MARKUP]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_info_dialog_get_buttons:
|
||||
* @self: a `GtkInfoDialog`
|
||||
*
|
||||
* Returns the button labels for the info dialog.
|
||||
*
|
||||
* Returns: (nullable) (transfer none): the button labels
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
const char * const *
|
||||
gtk_info_dialog_get_buttons (GtkInfoDialog *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_INFO_DIALOG (self), NULL);
|
||||
|
||||
return (const char * const *) self->buttons;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_info_dialog_set_buttons:
|
||||
* @self: a `GtkInfoDialog`
|
||||
* @labels: the new button labels
|
||||
*
|
||||
* Sets the button labels for the info dialog.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
void
|
||||
gtk_info_dialog_set_buttons (GtkInfoDialog *self,
|
||||
const char * const *labels)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_INFO_DIALOG (self));
|
||||
g_return_if_fail (labels != NULL);
|
||||
|
||||
g_strfreev (self->buttons);
|
||||
self->buttons = g_strdupv ((char **)labels);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_BUTTONS]);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Convenience API */
|
||||
|
||||
/**
|
||||
* gtk_info_dialog_set_heading_markup:
|
||||
* @self: a `GtkInfoDialog`
|
||||
* @text: the new heading
|
||||
*
|
||||
* Sets the heading that will be shown in the
|
||||
* info dialog, and marks it as using markup.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
void
|
||||
gtk_info_dialog_set_heading_markup (GtkInfoDialog *self,
|
||||
const char *text)
|
||||
{
|
||||
g_object_freeze_notify (G_OBJECT (self));
|
||||
gtk_info_dialog_set_heading (self, text);
|
||||
gtk_info_dialog_set_heading_use_markup (self, TRUE);
|
||||
g_object_thaw_notify (G_OBJECT (self));
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_info_dialog_set_body_markup:
|
||||
* @self: a `GtkInfoDialog`
|
||||
* @text: the new heading
|
||||
*
|
||||
* Sets the body text that will be shown in the
|
||||
* info dialog, and marks it as using markup.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
void
|
||||
gtk_info_dialog_set_body_markup (GtkInfoDialog *self,
|
||||
const char *text)
|
||||
{
|
||||
g_object_freeze_notify (G_OBJECT (self));
|
||||
gtk_info_dialog_set_body (self, text);
|
||||
gtk_info_dialog_set_body_use_markup (self, TRUE);
|
||||
g_object_thaw_notify (G_OBJECT (self));
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Async API */
|
||||
|
||||
static void response_cb (GTask *task,
|
||||
int response);
|
||||
|
||||
static void
|
||||
cancelled_cb (GCancellable *cancellable,
|
||||
GTask *task)
|
||||
{
|
||||
response_cb (task, -1);
|
||||
}
|
||||
|
||||
static void
|
||||
response_cb (GTask *task,
|
||||
int response)
|
||||
{
|
||||
GCancellable *cancellable;
|
||||
|
||||
cancellable = g_task_get_cancellable (task);
|
||||
|
||||
if (cancellable)
|
||||
g_signal_handlers_disconnect_by_func (cancellable, cancelled_cb, task);
|
||||
|
||||
if (response >= 0)
|
||||
g_task_return_int (task, response);
|
||||
else
|
||||
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_CANCELLED, "Cancelled");
|
||||
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static void
|
||||
dialog_response (GtkDialog *dialog,
|
||||
int response,
|
||||
GTask *task)
|
||||
{
|
||||
response_cb (task, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_info_dialog_present:
|
||||
* @self: a `GtkInfoDialog`
|
||||
* @parent: (nullable): the parent `GtkWindow`
|
||||
* @cancellable: (nullable): a `GCancellable` to cancel the operation
|
||||
* @callback: (scope async): a callback to call when the operation is complete
|
||||
* @user_data: (closure callback): data to pass to @callback
|
||||
*
|
||||
* This function presents an info dialog to the user.
|
||||
*
|
||||
* The @callback will be called when the dialog is dismissed.
|
||||
* It should call [function@Gtk.InfoDialog.present_finish]
|
||||
* to obtain the result.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
void
|
||||
gtk_info_dialog_present (GtkInfoDialog *self,
|
||||
GtkWindow *parent,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkMessageDialog *window;
|
||||
GTask *task;
|
||||
|
||||
g_return_if_fail (GTK_IS_INFO_DIALOG (self));
|
||||
|
||||
window = g_object_new (GTK_TYPE_MESSAGE_DIALOG,
|
||||
"transient-for", parent,
|
||||
"destroy-with-parent", TRUE,
|
||||
"modal", self->modal,
|
||||
"text", self->heading,
|
||||
"use-markup", self->heading_use_markup,
|
||||
"secondary-text", self->body,
|
||||
"secondary-use-markup", self->body_use_markup,
|
||||
NULL);
|
||||
|
||||
if (self->buttons)
|
||||
{
|
||||
for (int i = 0; self->buttons[i]; i++)
|
||||
gtk_dialog_add_button (GTK_DIALOG (window), self->buttons[i], i);
|
||||
}
|
||||
else
|
||||
gtk_dialog_add_button (GTK_DIALOG (window), _("Close"), 0);
|
||||
|
||||
task = g_task_new (self, cancellable, callback, user_data);
|
||||
g_task_set_source_tag (task, gtk_info_dialog_present);
|
||||
g_task_set_task_data (task, window, (GDestroyNotify) gtk_window_destroy);
|
||||
|
||||
if (cancellable)
|
||||
g_signal_connect (cancellable, "cancelled", G_CALLBACK (cancelled_cb), task);
|
||||
|
||||
g_signal_connect (window, "response", G_CALLBACK (dialog_response), task);
|
||||
|
||||
gtk_window_present (GTK_WINDOW (window));
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_info_dialog_present_finish:
|
||||
* @self: a `GtkInfoDialog`
|
||||
* @result: a `GAsyncResult`
|
||||
* @button: (out caller-allocates): return location for button
|
||||
* @error: return location for an error
|
||||
*
|
||||
* Finishes the [function@Gtk.InfoDialog.present] call
|
||||
* and returns the button that was clicked.
|
||||
*
|
||||
* Returns: `TRUE` if a button was clicked.
|
||||
* Otherwise, `FALSE` is returned and @error is set
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
gboolean
|
||||
gtk_info_dialog_present_finish (GtkInfoDialog *self,
|
||||
GAsyncResult *result,
|
||||
int *button,
|
||||
GError **error)
|
||||
{
|
||||
*button = (int) g_task_propagate_int (G_TASK (result), error);
|
||||
return ! (error && *error);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* vim:set foldmethod=marker expandtab: */
|
104
gtk/gtkinfodialog.h
Normal file
104
gtk/gtkinfodialog.h
Normal file
@@ -0,0 +1,104 @@
|
||||
/* GTK - The GIMP Toolkit
|
||||
*
|
||||
* Copyright (C) 2022 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gtk/gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <gtk/gtkwindow.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_INFO_DIALOG (gtk_info_dialog_get_type ())
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
G_DECLARE_FINAL_TYPE (GtkInfoDialog, gtk_info_dialog, GTK, INFO_DIALOG, GObject)
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
GtkInfoDialog * gtk_info_dialog_new (void);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
gboolean gtk_info_dialog_get_modal (GtkInfoDialog *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
void gtk_info_dialog_set_modal (GtkInfoDialog *self,
|
||||
gboolean modal);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
const char * gtk_info_dialog_get_heading (GtkInfoDialog *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
void gtk_info_dialog_set_heading (GtkInfoDialog *self,
|
||||
const char *text);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
void gtk_info_dialog_set_heading_markup (GtkInfoDialog *self,
|
||||
const char *text);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
gboolean gtk_info_dialog_get_heading_use_markup
|
||||
(GtkInfoDialog *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
void gtk_info_dialog_set_heading_use_markup
|
||||
(GtkInfoDialog *self,
|
||||
gboolean use_markup);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
const char * gtk_info_dialog_get_body (GtkInfoDialog *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
void gtk_info_dialog_set_body (GtkInfoDialog *self,
|
||||
const char *text);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
void gtk_info_dialog_set_body_markup (GtkInfoDialog *self,
|
||||
const char *text);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
gboolean gtk_info_dialog_get_body_use_markup (GtkInfoDialog *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
void gtk_info_dialog_set_body_use_markup (GtkInfoDialog *self,
|
||||
gboolean use_markup);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
void gtk_info_dialog_set_buttons (GtkInfoDialog *self,
|
||||
const char * const *labels);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
const char * const *
|
||||
gtk_info_dialog_get_buttons (GtkInfoDialog *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
void gtk_info_dialog_present (GtkInfoDialog *self,
|
||||
GtkWindow *parent,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
gboolean gtk_info_dialog_present_finish (GtkInfoDialog *self,
|
||||
GAsyncResult *result,
|
||||
int *button,
|
||||
GError **error);
|
||||
|
||||
G_END_DECLS
|
@@ -520,8 +520,6 @@ on_remove_server_button_clicked (RemoveServerData *data)
|
||||
populate_servers (data->view);
|
||||
}
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
|
||||
static void
|
||||
populate_servers (GtkPlacesView *view)
|
||||
{
|
||||
@@ -617,8 +615,6 @@ populate_servers (GtkPlacesView *view)
|
||||
g_bookmark_file_free (server_list);
|
||||
}
|
||||
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
|
||||
static void
|
||||
update_view_mode (GtkPlacesView *view)
|
||||
{
|
||||
|
@@ -24,12 +24,11 @@
|
||||
#include <gdk/gdk.h>
|
||||
|
||||
#include "gtksearchenginemodelprivate.h"
|
||||
#include "gtkfilechooserutils.h"
|
||||
#include "gtkprivate.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
|
||||
struct _GtkSearchEngineModel
|
||||
{
|
||||
GtkSearchEngine parent;
|
||||
@@ -81,37 +80,33 @@ static gboolean
|
||||
do_search (gpointer data)
|
||||
{
|
||||
GtkSearchEngineModel *model = data;
|
||||
GtkTreeIter iter;
|
||||
GList *hits = NULL;
|
||||
gboolean got_results = FALSE;
|
||||
|
||||
if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (model->model), &iter))
|
||||
for (guint i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (model->model)); i++)
|
||||
{
|
||||
do
|
||||
GFileInfo *info = g_list_model_get_item (G_LIST_MODEL (model->model), i);
|
||||
|
||||
if (info_matches_query (model->query, info))
|
||||
{
|
||||
GFileInfo *info;
|
||||
GFile *file;
|
||||
GtkSearchHit *hit;
|
||||
|
||||
info = _gtk_file_system_model_get_info (model->model, &iter);
|
||||
if (info_matches_query (model->query, info))
|
||||
{
|
||||
GFile *file;
|
||||
GtkSearchHit *hit;
|
||||
|
||||
file = _gtk_file_system_model_get_file (model->model, &iter);
|
||||
hit = g_new (GtkSearchHit, 1);
|
||||
hit->file = g_object_ref (file);
|
||||
hit->info = g_object_ref (info);
|
||||
hits = g_list_prepend (hits, hit);
|
||||
}
|
||||
file = _gtk_file_info_get_file (info);
|
||||
hit = g_new (GtkSearchHit, 1);
|
||||
hit->file = g_object_ref (file);
|
||||
hit->info = g_object_ref (info);
|
||||
hits = g_list_prepend (hits, hit);
|
||||
}
|
||||
while (gtk_tree_model_iter_next (GTK_TREE_MODEL (model->model), &iter));
|
||||
|
||||
if (hits)
|
||||
{
|
||||
_gtk_search_engine_hits_added (GTK_SEARCH_ENGINE (model), hits);
|
||||
g_list_free_full (hits, (GDestroyNotify)_gtk_search_hit_free);
|
||||
got_results = TRUE;
|
||||
}
|
||||
g_clear_object (&info);
|
||||
}
|
||||
|
||||
if (hits)
|
||||
{
|
||||
_gtk_search_engine_hits_added (GTK_SEARCH_ENGINE (model), hits);
|
||||
g_list_free_full (hits, (GDestroyNotify)_gtk_search_hit_free);
|
||||
got_results = TRUE;
|
||||
}
|
||||
|
||||
model->idle = 0;
|
||||
|
@@ -114,7 +114,8 @@ free_hit (gpointer data)
|
||||
}
|
||||
|
||||
static GFileInfo *
|
||||
create_file_info (TrackerSparqlCursor *cursor)
|
||||
create_file_info (GFile *file,
|
||||
TrackerSparqlCursor *cursor)
|
||||
{
|
||||
GFileInfo *info;
|
||||
const char *str;
|
||||
@@ -140,6 +141,10 @@ create_file_info (TrackerSparqlCursor *cursor)
|
||||
g_date_time_unref (creation);
|
||||
}
|
||||
|
||||
g_file_info_set_attribute_object (info, "standard::file", G_OBJECT (file));
|
||||
g_file_info_set_attribute_boolean (info, "filechooser::filtered-out", FALSE);
|
||||
g_file_info_set_attribute_boolean (info, "filechooser::visible", TRUE);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
@@ -175,7 +180,7 @@ query_callback (TrackerSparqlStatement *statement,
|
||||
url = tracker_sparql_cursor_get_string (cursor, 0, NULL);
|
||||
hit = g_slice_new0 (GtkSearchHit);
|
||||
hit->file = g_file_new_for_uri (url);
|
||||
hit->info = create_file_info (cursor);
|
||||
hit->info = create_file_info (hit->file, cursor);
|
||||
hits = g_list_prepend (hits, hit);
|
||||
}
|
||||
|
||||
|
@@ -1259,13 +1259,13 @@ property_editor (GObject *object,
|
||||
g_strdup_printf ("%s: %s",
|
||||
self->name,
|
||||
gtk_label_get_text (GTK_LABEL (prop_edit))),
|
||||
NULL);
|
||||
-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_accessible_update_property (GTK_ACCESSIBLE (prop_edit),
|
||||
GTK_ACCESSIBLE_PROPERTY_LABEL, self->name,
|
||||
NULL);
|
||||
-1);
|
||||
}
|
||||
|
||||
return prop_edit;
|
||||
|
@@ -72,7 +72,7 @@ add_string (GtkInspectorStrvEditor *editor,
|
||||
gtk_editable_set_text (GTK_EDITABLE (entry), str);
|
||||
gtk_accessible_update_property (GTK_ACCESSIBLE (entry),
|
||||
GTK_ACCESSIBLE_PROPERTY_LABEL, _("Value"),
|
||||
NULL);
|
||||
-1);
|
||||
gtk_widget_show (entry);
|
||||
gtk_box_append (GTK_BOX (box), entry);
|
||||
g_object_set_data (G_OBJECT (box), "entry", entry);
|
||||
@@ -83,7 +83,7 @@ add_string (GtkInspectorStrvEditor *editor,
|
||||
gtk_accessible_update_property (GTK_ACCESSIBLE (button),
|
||||
GTK_ACCESSIBLE_PROPERTY_LABEL,
|
||||
g_strdup_printf (_("Remove %s"), str),
|
||||
NULL);
|
||||
-1);
|
||||
gtk_widget_show (button);
|
||||
gtk_box_append (GTK_BOX (box), button);
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (remove_string), editor);
|
||||
@@ -116,7 +116,7 @@ gtk_inspector_strv_editor_init (GtkInspectorStrvEditor *editor)
|
||||
gtk_widget_set_halign (editor->button, GTK_ALIGN_END);
|
||||
gtk_accessible_update_property (GTK_ACCESSIBLE (editor->button),
|
||||
GTK_ACCESSIBLE_PROPERTY_LABEL, _("Add"),
|
||||
NULL);
|
||||
-1);
|
||||
gtk_widget_show (editor->button);
|
||||
g_signal_connect (editor->button, "clicked", G_CALLBACK (add_cb), editor);
|
||||
|
||||
|
@@ -108,7 +108,10 @@ gtk_private_sources = files([
|
||||
'gtkfilechoosererrorstack.c',
|
||||
'gtkfilechoosernativeportal.c',
|
||||
'gtkfilechooserutils.c',
|
||||
'gtkfilechoosercell.c',
|
||||
'gtkfiledialog.c',
|
||||
'gtkfilesystemmodel.c',
|
||||
'gtkfilethumbnail.c',
|
||||
'gtkgizmo.c',
|
||||
'gtkiconcache.c',
|
||||
'gtkiconcachevalidator.c',
|
||||
@@ -180,10 +183,13 @@ gtk_public_sources = files([
|
||||
'gtkcenterbox.c',
|
||||
'gtkcenterlayout.c',
|
||||
'gtkcheckbutton.c',
|
||||
'gtkchoice.c',
|
||||
'gtkcolorbutton.c',
|
||||
'gtkcolorchooser.c',
|
||||
'gtkcolorchooserdialog.c',
|
||||
'gtkcolorchooserwidget.c',
|
||||
'gtkcolordialog.c',
|
||||
'gtkcolordialogbutton.c',
|
||||
'gtkcolorutils.c',
|
||||
'gtkcolumnview.c',
|
||||
'gtkcolumnviewcolumn.c',
|
||||
@@ -235,6 +241,8 @@ gtk_public_sources = files([
|
||||
'gtkfontchooserdialog.c',
|
||||
'gtkfontchooserutils.c',
|
||||
'gtkfontchooserwidget.c',
|
||||
'gtkfontdialog.c',
|
||||
'gtkfontdialogbutton.c',
|
||||
'gtkframe.c',
|
||||
'gtkgesture.c',
|
||||
'gtkgesturedrag.c',
|
||||
@@ -259,6 +267,7 @@ gtk_public_sources = files([
|
||||
'gtkimmodule.c',
|
||||
'gtkimmulticontext.c',
|
||||
'gtkinfobar.c',
|
||||
'gtkinfodialog.c',
|
||||
'gtkinscription.c',
|
||||
'gtklabel.c',
|
||||
'gtklayoutchild.c',
|
||||
@@ -436,10 +445,13 @@ gtk_public_headers = files([
|
||||
'gtkcenterbox.h',
|
||||
'gtkcenterlayout.h',
|
||||
'gtkcheckbutton.h',
|
||||
'gtkchoice.h',
|
||||
'gtkcolorbutton.h',
|
||||
'gtkcolorchooser.h',
|
||||
'gtkcolorchooserdialog.h',
|
||||
'gtkcolorchooserwidget.h',
|
||||
'gtkcolordialog.h',
|
||||
'gtkcolordialogbutton.h',
|
||||
'gtkcolorutils.h',
|
||||
'gtkcolumnview.h',
|
||||
'gtkcolumnviewcolumn.h',
|
||||
@@ -479,6 +491,7 @@ gtk_public_headers = files([
|
||||
'gtkfilechooserdialog.h',
|
||||
'gtkfilechoosernative.h',
|
||||
'gtkfilechooserwidget.h',
|
||||
'gtkfiledialog.h',
|
||||
'gtkfilefilter.h',
|
||||
'gtkfilter.h',
|
||||
'gtkfilterlistmodel.h',
|
||||
@@ -490,6 +503,8 @@ gtk_public_headers = files([
|
||||
'gtkfontchooser.h',
|
||||
'gtkfontchooserdialog.h',
|
||||
'gtkfontchooserwidget.h',
|
||||
'gtkfontdialog.h',
|
||||
'gtkfontdialogbutton.h',
|
||||
'gtkframe.h',
|
||||
'gtkgesture.h',
|
||||
'gtkgesturedrag.h',
|
||||
@@ -513,6 +528,7 @@ gtk_public_headers = files([
|
||||
'gtkimmodule.h',
|
||||
'gtkimmulticontext.h',
|
||||
'gtkinfobar.h',
|
||||
'gtkinfodialog.h',
|
||||
'gtkinscription.h',
|
||||
'gtklabel.h',
|
||||
'gtklayoutchild.h',
|
||||
|
@@ -3369,6 +3369,30 @@ columnview row:not(:selected) cell editablelabel.editing text selection {
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************
|
||||
* Complex Lists *
|
||||
* Put padding on the cell content so event controllers *
|
||||
* can cover the whole area. *
|
||||
********************************************************/
|
||||
|
||||
columnview.complex {
|
||||
> listview > row > cell {
|
||||
padding: 0;
|
||||
> * {
|
||||
padding: 8px 6px;
|
||||
}
|
||||
}
|
||||
|
||||
// shrink vertically for .data-table
|
||||
&.data-table > listview > row > cell {
|
||||
padding: 0;
|
||||
> * {
|
||||
padding-top: 2px;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************
|
||||
* App Notifications *
|
||||
*********************/
|
||||
|
@@ -140,103 +140,278 @@
|
||||
<property name="hscrollbar-policy">2</property>
|
||||
<property name="vexpand">1</property>
|
||||
<child>
|
||||
<object class="GtkTreeView" id="browse_files_tree_view">
|
||||
<property name="has-tooltip">1</property>
|
||||
<property name="enable-search">0</property>
|
||||
<object class="GtkColumnView" id="browse_files_column_view">
|
||||
<style>
|
||||
<class name="complex"/>
|
||||
</style>
|
||||
<signal name="activate" handler="column_view_row_activated_cb" swapped="no"/>
|
||||
<signal name="keynav-failed" handler="browse_files_column_view_keynav_failed_cb"/>
|
||||
<child>
|
||||
<object class="GtkGestureLongPress">
|
||||
<property name="touch-only">1</property>
|
||||
<signal name="pressed" handler="long_press_cb" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkGestureClick">
|
||||
<property name="button">3</property>
|
||||
<signal name="pressed" handler="click_cb" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<signal name="query-tooltip" handler="file_list_query_tooltip_cb" swapped="no"/>
|
||||
<signal name="row-activated" handler="list_row_activated" swapped="no"/>
|
||||
<signal name="keynav-failed" handler="browse_files_tree_view_keynav_failed_cb"/>
|
||||
<child internal-child="selection">
|
||||
<object class="GtkTreeSelection" id="treeview-selection2">
|
||||
<signal name="changed" handler="list_selection_changed" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="list_name_column">
|
||||
<object class="GtkColumnViewColumn" id="column_view_name_column">
|
||||
<property name="title" translatable="yes">Name</property>
|
||||
<property name="resizable">1</property>
|
||||
<property name="expand">1</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererPixbuf" id="list_pixbuf_renderer">
|
||||
<property name="xpad">6</property>
|
||||
<property name="resizable">1</property>
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="bytes"><![CDATA[
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="GtkFileChooserCell">
|
||||
<binding name="position">
|
||||
<lookup name="position">GtkListItem</lookup>
|
||||
</binding>
|
||||
<binding name="item">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</binding>
|
||||
<binding name="selected">
|
||||
<lookup name="selected">GtkListItem</lookup>
|
||||
</binding>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<binding name="tooltip-text">
|
||||
<closure type="gchararray" function="column_view_get_tooltip_text">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</closure>
|
||||
</binding>
|
||||
<child>
|
||||
<object class="GtkFileThumbnail">
|
||||
<property name="margin-start">6</property>
|
||||
<property name="margin-end">6</property>
|
||||
<binding name="file-info">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</binding>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkInscription">
|
||||
<property name="hexpand">1</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="min-chars">10</property>
|
||||
<binding name="text">
|
||||
<closure type="gchararray" function="column_view_get_file_display_name">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</closure>
|
||||
</binding>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
</interface>
|
||||
]]></property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCellRendererText" id="list_name_renderer">
|
||||
<property name="width-chars">10</property>
|
||||
<property name="ellipsize">3</property>
|
||||
</object>
|
||||
</child>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="list_location_column">
|
||||
<object class="GtkColumnViewColumn" id="column_view_location_column">
|
||||
<property name="title" translatable="yes">Location</property>
|
||||
<property name="resizable">1</property>
|
||||
<property name="visible">0</property>
|
||||
<property name="expand">1</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText" id="list_location_renderer">
|
||||
<property name="xalign">0</property>
|
||||
<property name="width-chars">10</property>
|
||||
<property name="ellipsize">1</property>
|
||||
<property name="xpad">6</property>
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="bytes"><![CDATA[
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="GtkFileChooserCell">
|
||||
<binding name="position">
|
||||
<lookup name="position">GtkListItem</lookup>
|
||||
</binding>
|
||||
<binding name="item">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</binding>
|
||||
<binding name="selected">
|
||||
<lookup name="selected">GtkListItem</lookup>
|
||||
</binding>
|
||||
<child>
|
||||
<object class="GtkInscription">
|
||||
<property name="hexpand">1</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="min-chars">10</property>
|
||||
<property name="margin-start">6</property>
|
||||
<property name="margin-end">6</property>
|
||||
<binding name="text">
|
||||
<closure type="gchararray" function="column_view_get_location">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</closure>
|
||||
</binding>
|
||||
<binding name="tooltip-text">
|
||||
<closure type="gchararray" function="column_view_get_tooltip_text">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</closure>
|
||||
</binding>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
</interface>
|
||||
]]></property>
|
||||
</object>
|
||||
</child>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="list_size_column">
|
||||
<object class="GtkColumnViewColumn" id="column_view_size_column">
|
||||
<property name="title" translatable="yes">Size</property>
|
||||
<property name="sizing">2</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText" id="list_size_renderer">
|
||||
<property name="xalign">0</property>
|
||||
<property name="xpad">6</property>
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="bytes"><![CDATA[
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="GtkFileChooserCell">
|
||||
<binding name="position">
|
||||
<lookup name="position">GtkListItem</lookup>
|
||||
</binding>
|
||||
<binding name="item">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</binding>
|
||||
<binding name="selected">
|
||||
<lookup name="selected">GtkListItem</lookup>
|
||||
</binding>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="hexpand">1</property>
|
||||
<property name="xalign">0</property>
|
||||
<binding name="label">
|
||||
<closure type="gchararray" function="column_view_get_size">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</closure>
|
||||
</binding>
|
||||
<binding name="tooltip-text">
|
||||
<closure type="gchararray" function="column_view_get_tooltip_text">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</closure>
|
||||
</binding>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
</interface>
|
||||
]]></property>
|
||||
</object>
|
||||
</child>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="list_type_column">
|
||||
<object class="GtkColumnViewColumn" id="column_view_type_column">
|
||||
<property name="title" translatable="yes">Type</property>
|
||||
<property name="resizable">1</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText" id="list_type_renderer">
|
||||
<property name="xalign">0</property>
|
||||
<property name="xpad">6</property>
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="bytes"><![CDATA[
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="GtkFileChooserCell">
|
||||
<binding name="position">
|
||||
<lookup name="position">GtkListItem</lookup>
|
||||
</binding>
|
||||
<binding name="item">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</binding>
|
||||
<binding name="selected">
|
||||
<lookup name="selected">GtkListItem</lookup>
|
||||
</binding>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="hexpand">1</property>
|
||||
<property name="xalign">0</property>
|
||||
<binding name="label">
|
||||
<closure type="gchararray" function="column_view_get_file_type">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</closure>
|
||||
</binding>
|
||||
<binding name="tooltip-text">
|
||||
<closure type="gchararray" function="column_view_get_tooltip_text">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</closure>
|
||||
</binding>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
</interface>
|
||||
]]></property>
|
||||
</object>
|
||||
</child>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="list_time_column">
|
||||
<object class="GtkColumnViewColumn" id="column_view_time_column">
|
||||
<property name="title" translatable="yes">Modified</property>
|
||||
<property name="sizing">2</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText" id="list_date_renderer">
|
||||
<property name="xpad">6</property>
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="bytes"><![CDATA[
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="GtkFileChooserCell" id="file_chooser_cell">
|
||||
<binding name="position">
|
||||
<lookup name="position">GtkListItem</lookup>
|
||||
</binding>
|
||||
<binding name="item">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</binding>
|
||||
<binding name="selected">
|
||||
<lookup name="selected">GtkListItem</lookup>
|
||||
</binding>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="spacing">6</property>
|
||||
<binding name="tooltip-text">
|
||||
<closure type="gchararray" function="column_view_get_tooltip_text">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</closure>
|
||||
</binding>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<binding name="label">
|
||||
<closure type="gchararray" function="column_view_get_file_date">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</closure>
|
||||
</binding>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible" bind-source="file_chooser_cell" bind-property="show-time" bind-flags="sync-create"/>
|
||||
<binding name="label">
|
||||
<closure type="gchararray" function="column_view_get_file_time">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</closure>
|
||||
</binding>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
</interface>
|
||||
]]></property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCellRendererText" id="list_time_renderer">
|
||||
<property name="xpad">6</property>
|
||||
</object>
|
||||
</child>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
@@ -10,7 +10,7 @@ project('gtk', 'c',
|
||||
meson_version : '>= 0.60.0',
|
||||
license: 'LGPL-2.1-or-later')
|
||||
|
||||
glib_req = '>= 2.66.0'
|
||||
glib_req = '>= 2.72.0'
|
||||
pango_req = '>= 1.50.0' # keep this in sync with .gitlab-ci/test-msys.sh
|
||||
harfbuzz_req = '>= 2.6.0'
|
||||
fribidi_req = '>= 0.19.7'
|
||||
|
Reference in New Issue
Block a user