Compare commits
216 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c85905dfcd | |||
| e2eba253cb | |||
| 09d1129f4f | |||
| affa829ac2 | |||
| da397664b4 | |||
| d3b32e9f42 | |||
| e2d92863b2 | |||
| f9e1e7bd1a | |||
| 641c068744 | |||
| 7c8cd23c5f | |||
| 6aafb81702 | |||
| 0578422612 | |||
| ad04da84c9 | |||
| 333b013f7f | |||
| b3dc517565 | |||
| 70e4dabe89 | |||
| d3443d6f2a | |||
| a508f68044 | |||
| f191b64bbc | |||
| e9efe77839 | |||
| d98c0d32f2 | |||
| dfa2dcceb8 | |||
| d441e7106b | |||
| 4cd92f979c | |||
| d1a068e5b1 | |||
| 4d90846182 | |||
| 986f721938 | |||
| 7903246355 | |||
| 0252ae2be3 | |||
| fa90e42a38 | |||
| 2d36109565 | |||
| de8258171a | |||
| 2ed6224778 | |||
| e1a0171094 | |||
| 395521f3d3 | |||
| 8c95a84ea4 | |||
| 75db19c789 | |||
| f00d2b30bb | |||
| c0c5ce2f9b | |||
| ee9f9ae05e | |||
| 387649ded4 | |||
| be12131d74 | |||
| 896ebdc9d7 | |||
| bc58bd0b83 | |||
| 8d4c87876b | |||
| cebc99ddc7 | |||
| 1b62203f18 | |||
| 06dd8c2cfd | |||
| 5da21ca4dc | |||
| 3e16ef33b0 | |||
| 2746a2d929 | |||
| e31bacf7be | |||
| 911ae64931 | |||
| 99a0b35705 | |||
| 89bf8af878 | |||
| f3744c991a | |||
| dcee15c0f1 | |||
| 2321e9de05 | |||
| 73dcda460f | |||
| 0f8bc67a98 | |||
| 379d830123 | |||
| bc8bc68b80 | |||
| 8c4df51a14 | |||
| 06d67d2384 | |||
| cc8bb5fc54 | |||
| 8fb1e33d0f | |||
| 0dc946da63 | |||
| 26a23d3e56 | |||
| 766f4bc8fe | |||
| 3d008d5929 | |||
| 0546e26434 | |||
| e6d8eedc00 | |||
| 13b37b0ba4 | |||
| 779c71b66d | |||
| 8e73d007f5 | |||
| e376d638fb | |||
| 52982a88aa | |||
| 422c1d9c0d | |||
| ccc8ad8700 | |||
| 6b0eb970d8 | |||
| 775e35865c | |||
| 49ce680d53 | |||
| 463f3d3a52 | |||
| f6347f18b0 | |||
| 2e959fe300 | |||
| 56f771ba29 | |||
| 32e96215b4 | |||
| 86f800e11d | |||
| 4d371b2b16 | |||
| 7e97c2513f | |||
| 2bf5a150e6 | |||
| 18c87faaa5 | |||
| fdeda388bf | |||
| ea2c27c640 | |||
| dfc04a590d | |||
| fe5b364675 | |||
| 9b73c55559 | |||
| 0b38a0663d | |||
| e5c0716293 | |||
| 54a3293cad | |||
| 818287a7ce | |||
| 59119cd898 | |||
| 817da34f7e | |||
| 8fa44fc3e6 | |||
| c7e94151b2 | |||
| 729ba44297 | |||
| 2a2a6879c5 | |||
| e7b773b031 | |||
| 57a225681c | |||
| ea07a92366 | |||
| 76290e8ddb | |||
| 26d83b1ab7 | |||
| 2bba856206 | |||
| bf3382a89e | |||
| 3162e25671 | |||
| 3d931b4fe2 | |||
| fc770a383a | |||
| 62c385a9dd | |||
| 7c4ad1a5c4 | |||
| ac524bb13a | |||
| 66fa9380b5 | |||
| b64eb6ca13 | |||
| 9b2d8ac362 | |||
| 2a90bc1a9b | |||
| d4b868d9bc | |||
| b54f6710a7 | |||
| 6bb7caf155 | |||
| 202348f9d0 | |||
| 1a613de2f6 | |||
| 665df37703 | |||
| acad5e4e3d | |||
| 6267c8469b | |||
| 5a2f791bdd | |||
| 286a00a1db | |||
| 11dd602b28 | |||
| 35988d659d | |||
| be3449b3ce | |||
| 2d8fddc1e9 | |||
| 644d522d19 | |||
| a8b0125da1 | |||
| acccac516e | |||
| d65214fa4e | |||
| 1d96fc8237 | |||
| 882a87ca19 | |||
| 1dbb8df95f | |||
| f6c2c2edbd | |||
| c4e4de36f6 | |||
| 67cbb2a7d3 | |||
| a979daa8ea | |||
| fb14f50ec1 | |||
| 6099fbafc1 | |||
| 6f2f828bce | |||
| 795d3122cc | |||
| 5080730728 | |||
| f75a3a0e95 | |||
| b75db7d1c6 | |||
| b03069bdf6 | |||
| 1c71e56e75 | |||
| 9332d0dcc8 | |||
| 9ad37583e6 | |||
| 69975627e9 | |||
| b74a489aba | |||
| 599b807726 | |||
| 6510ca8bdd | |||
| be20a04e04 | |||
| 92e5536335 | |||
| c2da2f7ecd | |||
| 54bfd380a8 | |||
| f01d695e6c | |||
| 619b2465c1 | |||
| cc18191a8e | |||
| 1f8e7c8aab | |||
| 671daea262 | |||
| 76533513c2 | |||
| 0d3988365b | |||
| 0966636803 | |||
| 7c3b30036e | |||
| 988901294d | |||
| 43b9fc6981 | |||
| 25f670faae | |||
| d0068a036f | |||
| fae014eb45 | |||
| f0ea0be15d | |||
| 9650236b23 | |||
| c0e2d7c62f | |||
| cc072eb7cd | |||
| 613213f597 | |||
| e25c25fcb5 | |||
| 52666d6fe5 | |||
| 56b3669411 | |||
| e3b5b76cdd | |||
| bbb28196e5 | |||
| 72d3a9042c | |||
| f2853ffa8e | |||
| fca2ba963d | |||
| 806779769e | |||
| 82aa0d1f7c | |||
| 72f1d34eca | |||
| c267a75eef | |||
| 2fb755e0c9 | |||
| cd096819d8 | |||
| 83543423e2 | |||
| d0bb72a2aa | |||
| 8cc2a44268 | |||
| 4800dd3f95 | |||
| 2534310ce9 | |||
| 3a4fbc5e50 | |||
| 89a67ac719 | |||
| 21b84b1890 | |||
| 20935f678b | |||
| c41b4130c6 | |||
| f1b010af66 | |||
| ec1133d6e1 | |||
| 8fcf1b78a4 | |||
| 21f9148155 | |||
| d4f0593b37 |
+18
-2
@@ -19,8 +19,8 @@ variables:
|
||||
COMMON_MESON_FLAGS: "--fatal-meson-warnings --werror"
|
||||
BACKEND_FLAGS: "-Dx11-backend=true -Dwayland-backend=true -Dbroadway-backend=true -Dvulkan=yes"
|
||||
FEATURE_FLAGS: "-Dcloudproviders=true"
|
||||
MESON_TEST_TIMEOUT_MULTIPLIER: 2
|
||||
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v17"
|
||||
MESON_TEST_TIMEOUT_MULTIPLIER: 3
|
||||
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v20"
|
||||
FLATPAK_IMAGE: "registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:master"
|
||||
DOCS_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora-docs:v19"
|
||||
|
||||
@@ -180,6 +180,22 @@ static-scan:
|
||||
- _scan_build/meson-logs
|
||||
allow_failure: true
|
||||
|
||||
# Run tests with the address sanitizer. We need to turn off introspection,
|
||||
# since it is incompatible with asan
|
||||
asan-build:
|
||||
image: $FEDORA_IMAGE
|
||||
tags: [ privileged ]
|
||||
stage: analysis
|
||||
variables:
|
||||
script:
|
||||
- CC=clang meson --buildtype=debugoptimized -Db_sanitize=address -Db_lundef=false -Dintrospection=false _build
|
||||
- ninja -C _build
|
||||
- .gitlab-ci/run-tests.sh _build wayland
|
||||
artifacts:
|
||||
paths:
|
||||
- _build/meson-logs
|
||||
allow_failure: true
|
||||
|
||||
reference:
|
||||
image: $DOCS_IMAGE
|
||||
stage: docs
|
||||
|
||||
@@ -35,4 +35,13 @@ branch, as well as their available versions.
|
||||
- [ ] Add the new job to `.gitlab-ci.yml` referencing the image
|
||||
- [ ] Open a merge request with your changes and let it run
|
||||
|
||||
### Checklist for Adding a new dependency to a CI image
|
||||
|
||||
Our images are layered, and the base (called fedora-base) contains
|
||||
all the rpm payload. Therefore, adding a new dependency is a 2-step
|
||||
process:
|
||||
|
||||
1. [ ] Build and upload fedora-base:$version+1
|
||||
1. [ ] Build and upload fedora:$version+1 based on fedora-base:version+1
|
||||
|
||||
[registry]: https://gitlab.gnome.org/GNOME/gtk/container_registry
|
||||
|
||||
@@ -41,12 +41,14 @@ RUN dnf -y install \
|
||||
itstool \
|
||||
json-glib-devel \
|
||||
lcov \
|
||||
libasan \
|
||||
libattr-devel \
|
||||
libepoxy-devel \
|
||||
libffi-devel \
|
||||
libmount-devel \
|
||||
librsvg2 \
|
||||
libselinux-devel \
|
||||
libubsan \
|
||||
libXcomposite-devel \
|
||||
libXcursor-devel \
|
||||
libXcursor-devel \
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM registry.gitlab.gnome.org/gnome/gtk/fedora-base:v19
|
||||
FROM registry.gitlab.gnome.org/gnome/gtk/fedora-base:v20
|
||||
|
||||
ARG HOST_USER_ID=5555
|
||||
ENV HOST_USER_ID ${HOST_USER_ID}
|
||||
|
||||
@@ -7,10 +7,14 @@ srcdir=$( pwd )
|
||||
builddir=$1
|
||||
backend=$2
|
||||
|
||||
# Ignore memory leaks lower in dependencies
|
||||
export LSAN_OPTIONS=suppressions=$srcdir/lsan.supp
|
||||
|
||||
case "${backend}" in
|
||||
x11)
|
||||
xvfb-run -a -s "-screen 0 1024x768x24" \
|
||||
meson test -C ${builddir} \
|
||||
--timeout-multiplier "${MESON_TEST_TIMEOUT_MULTIPLIER}" \
|
||||
--print-errorlogs \
|
||||
--setup=${backend} \
|
||||
--suite=gtk \
|
||||
@@ -30,6 +34,7 @@ case "${backend}" in
|
||||
export WAYLAND_DISPLAY=wayland-5
|
||||
|
||||
meson test -C ${builddir} \
|
||||
--timeout-multiplier "${MESON_TEST_TIMEOUT_MULTIPLIER}" \
|
||||
--print-errorlogs \
|
||||
--setup=${backend} \
|
||||
--suite=gtk \
|
||||
@@ -48,6 +53,7 @@ case "${backend}" in
|
||||
export BROADWAY_DISPLAY=:5
|
||||
|
||||
meson test -C ${builddir} \
|
||||
--timeout-multiplier "${MESON_TEST_TIMEOUT_MULTIPLIER}" \
|
||||
--print-errorlogs \
|
||||
--setup=${backend} \
|
||||
--suite=gtk \
|
||||
|
||||
@@ -1,3 +1,74 @@
|
||||
Overview of Changes in GTK 3.99.0
|
||||
=================================
|
||||
|
||||
* Add GtkEditableLabel
|
||||
|
||||
* Add GtkBookmarkList, a list model for bookmarks
|
||||
|
||||
* Add GtkStringList, a list model for strings
|
||||
|
||||
* Add GtkBitset, and use it for representing selections
|
||||
|
||||
* GtkTreeView:
|
||||
- Make cell editing work again
|
||||
|
||||
* GtkSpinButton:
|
||||
- Make autosizing work again
|
||||
|
||||
* Printing:
|
||||
- Use GtkDropDown in the print dialog
|
||||
|
||||
* GtkApplication
|
||||
- Support opening files on OS X
|
||||
|
||||
* GtkFileChooser:
|
||||
- Fix libcloudproviders support
|
||||
- Turn GtkFileFilter into a GtkFilter
|
||||
- Simplify the api
|
||||
|
||||
* GtkGridView, GtkListView:
|
||||
- Improve scrolling behavior
|
||||
- Autoscroll and autoexpand during DND
|
||||
|
||||
* GtkFilterListModel:
|
||||
- Add incremental filtering
|
||||
|
||||
* GtkEntry:
|
||||
- Make entry completion work again
|
||||
- Drop action support from GtkEntryCompletion
|
||||
|
||||
* Inspector:
|
||||
- Improve list model support
|
||||
- Add direct navigation between objects
|
||||
|
||||
* GDK:
|
||||
- Compress scroll events
|
||||
- Keep a scroll history
|
||||
- Clean up GdkDevice api
|
||||
- Improve frame clock accuracy
|
||||
|
||||
* GSK:
|
||||
- Use gL_ARB_framebuffer_object
|
||||
|
||||
* gtk-demo:
|
||||
- Add incremental refill to the color grid
|
||||
- Improve performance of the color grid
|
||||
- Add an incrementally filtering word list
|
||||
|
||||
* Translation updates
|
||||
Basque
|
||||
Catalan
|
||||
Chinese
|
||||
Japanese
|
||||
Kazakh
|
||||
Lithuanian
|
||||
Polish
|
||||
Romanian
|
||||
Spanish
|
||||
Turkish
|
||||
Ukrainian
|
||||
|
||||
|
||||
Overview of Changes in GTK 3.98.5
|
||||
=================================
|
||||
|
||||
|
||||
@@ -15,7 +15,13 @@ if 'DESTDIR' not in os.environ:
|
||||
gtk_immodule_dir = os.path.join(gtk_moduledir, 'immodules')
|
||||
|
||||
print('Compiling GSettings schemas...')
|
||||
subprocess.call(['glib-compile-schemas',
|
||||
glib_compile_schemas = subprocess.check_output(['pkg-config',
|
||||
'--variable=glib_compile_schemas',
|
||||
'gio-2.0']).strip()
|
||||
if not os.path.exists(glib_compile_schemas):
|
||||
# pkg-config variables only available since GLib 2.62.0.
|
||||
glib_compile_schemas = 'glib-compile-schemas'
|
||||
subprocess.call([glib_compile_schemas,
|
||||
os.path.join(gtk_datadir, 'glib-2.0', 'schemas')])
|
||||
|
||||
print('Updating icon cache...')
|
||||
@@ -24,8 +30,14 @@ if 'DESTDIR' not in os.environ:
|
||||
|
||||
print('Updating module cache for print backends...')
|
||||
os.makedirs(gtk_printmodule_dir, exist_ok=True)
|
||||
subprocess.call(['gio-querymodules', gtk_printmodule_dir])
|
||||
gio_querymodules = subprocess.check_output(['pkg-config',
|
||||
'--variable=gio_querymodules',
|
||||
'gio-2.0']).strip()
|
||||
if not os.path.exists(gio_querymodules):
|
||||
# pkg-config variables only available since GLib 2.62.0.
|
||||
gio_querymodules = 'gio-querymodules'
|
||||
subprocess.call([gio_querymodules, gtk_printmodule_dir])
|
||||
|
||||
print('Updating module cache for input methods...')
|
||||
os.makedirs(gtk_immodule_dir, exist_ok=True)
|
||||
subprocess.call(['gio-querymodules', gtk_immodule_dir])
|
||||
subprocess.call([gio_querymodules, gtk_immodule_dir])
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
<property name="default-height">768</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child type="start">
|
||||
<object class="GtkButton">
|
||||
<property name="icon-name">document-open-symbolic</property>
|
||||
|
||||
@@ -188,7 +188,7 @@ constraint_view_init (ConstraintView *self)
|
||||
g_list_store_append (list, children);
|
||||
g_list_store_append (list, guides);
|
||||
g_list_store_append (list, constraints);
|
||||
self->model = G_LIST_MODEL (gtk_flatten_list_model_new (G_TYPE_OBJECT, G_LIST_MODEL (list)));
|
||||
self->model = G_LIST_MODEL (gtk_flatten_list_model_new (G_LIST_MODEL (list)));
|
||||
g_object_unref (children);
|
||||
g_object_unref (guides);
|
||||
g_object_unref (constraints);
|
||||
|
||||
@@ -140,6 +140,7 @@
|
||||
</gresource>
|
||||
<gresource prefix="/listview_colors">
|
||||
<file compressed="true">color.names.txt</file>
|
||||
<file>listview_colors.css</file>
|
||||
</gresource>
|
||||
<gresource prefix="/shortcuts">
|
||||
<file>shortcuts.ui</file>
|
||||
|
||||
+179
-29
@@ -1,13 +1,15 @@
|
||||
/* Drop Downs
|
||||
/* Lists/Selections
|
||||
*
|
||||
* The GtkDropDown widget is a modern alternative to GtkComboBox.
|
||||
* It uses list models instead of tree models, and the content is
|
||||
* displayed using widgets instead of cell renderers.
|
||||
* The GtkDropDown and GtkSuggestionEntry widgets are modern
|
||||
* alternatives to GtkComboBox and GtkEntryCompletion.
|
||||
*
|
||||
* They use list models instead of tree models, and the content
|
||||
* is displayed using widgets instead of cell renderers.
|
||||
*
|
||||
* The examples here demonstrate how to use different kinds of
|
||||
* list models with GtkDropDown, how to use search and how to
|
||||
* display the selected item differently from the presentation
|
||||
* in the popup.
|
||||
* list models with GtkDropDown and GtkSuggestionEntry, how to
|
||||
* use search and how to display the selected item differently
|
||||
* from the presentation in the popup.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
@@ -92,7 +94,7 @@ strings_setup_item_full (GtkSignalListItemFactory *factory,
|
||||
gtk_label_set_xalign (GTK_LABEL (title), 0.0);
|
||||
description = gtk_label_new ("");
|
||||
gtk_label_set_xalign (GTK_LABEL (description), 0.0);
|
||||
gtk_style_context_add_class (gtk_widget_get_style_context (description), "dim-label");
|
||||
gtk_widget_add_css_class (description, "dim-label");
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
|
||||
box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
|
||||
@@ -218,13 +220,50 @@ get_title (gpointer item)
|
||||
return g_strdup (STRING_HOLDER (item)->title);
|
||||
}
|
||||
|
||||
static char *
|
||||
get_file_name (gpointer item)
|
||||
{
|
||||
return g_strdup (g_file_info_get_display_name (G_FILE_INFO (item)));
|
||||
}
|
||||
|
||||
static void
|
||||
setup_item (GtkSignalListItemFactory *factory,
|
||||
GtkListItem *item)
|
||||
{
|
||||
GtkWidget *box;
|
||||
GtkWidget *icon;
|
||||
GtkWidget *label;
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
|
||||
icon = gtk_image_new ();
|
||||
label = gtk_label_new ("");
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 0);
|
||||
gtk_box_append (GTK_BOX (box), icon);
|
||||
gtk_box_append (GTK_BOX (box), label);
|
||||
gtk_list_item_set_child (item, box);
|
||||
}
|
||||
|
||||
static void
|
||||
bind_item (GtkSignalListItemFactory *factory,
|
||||
GtkListItem *item)
|
||||
{
|
||||
GFileInfo *info = G_FILE_INFO (gtk_list_item_get_item (item));
|
||||
GtkWidget *box = gtk_list_item_get_child (item);
|
||||
GtkWidget *icon = gtk_widget_get_first_child (box);
|
||||
GtkWidget *label = gtk_widget_get_last_child (box);
|
||||
|
||||
gtk_image_set_from_gicon (GTK_IMAGE (icon), g_file_info_get_icon (info));
|
||||
gtk_label_set_label (GTK_LABEL (label), g_file_info_get_display_name (info));
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_dropdown (GtkWidget *do_widget)
|
||||
{
|
||||
static GtkWidget *window = NULL;
|
||||
GtkWidget *button, *box, *spin, *check;
|
||||
GtkWidget *button, *box, *spin, *check, *hbox, *label, *entry;
|
||||
GListModel *model;
|
||||
GtkExpression *expression;
|
||||
GtkListItemFactory *factory;
|
||||
const char * const times[] = { "1 minute", "2 minutes", "5 minutes", "20 minutes", NULL };
|
||||
const char * const many_times[] = {
|
||||
"1 minute", "2 minutes", "5 minutes", "10 minutes", "15 minutes", "20 minutes",
|
||||
@@ -237,23 +276,78 @@ do_dropdown (GtkWidget *do_widget)
|
||||
const char * const device_descriptions[] = {
|
||||
"Built-in Audio", "Built-in audio", "Thinkpad Tunderbolt 3 Dock USB Audio", "Thinkpad Tunderbolt 3 Dock USB Audio", NULL
|
||||
};
|
||||
const char *words[] = {
|
||||
"GNOME",
|
||||
"gnominious",
|
||||
"Gnomonic projection",
|
||||
"total",
|
||||
"totally",
|
||||
"toto",
|
||||
"tottery",
|
||||
"totterer",
|
||||
"Totten trust",
|
||||
"totipotent",
|
||||
"totipotency",
|
||||
"totemism",
|
||||
"totem pole",
|
||||
"Totara",
|
||||
"totalizer",
|
||||
"totalizator",
|
||||
"totalitarianism",
|
||||
"total parenteral nutrition",
|
||||
"total hysterectomy",
|
||||
"total eclipse",
|
||||
"Totipresence",
|
||||
"Totipalmi",
|
||||
"Tomboy",
|
||||
"zombie",
|
||||
NULL
|
||||
};
|
||||
|
||||
char *cwd;
|
||||
GFile *file;
|
||||
GListModel *dir;
|
||||
|
||||
if (!window)
|
||||
{
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Drop Downs");
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Selections");
|
||||
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
|
||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
|
||||
gtk_widget_set_margin_start (box, 10);
|
||||
gtk_widget_set_margin_end (box, 10);
|
||||
gtk_widget_set_margin_top (box, 10);
|
||||
gtk_widget_set_margin_bottom (box, 10);
|
||||
gtk_window_set_child (GTK_WINDOW (window), box);
|
||||
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 20);
|
||||
|
||||
gtk_widget_set_margin_start (hbox, 20);
|
||||
gtk_widget_set_margin_end (hbox, 20);
|
||||
gtk_widget_set_margin_top (hbox, 20);
|
||||
gtk_widget_set_margin_bottom (hbox, 20);
|
||||
gtk_window_set_child (GTK_WINDOW (window), hbox);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
|
||||
gtk_box_append (GTK_BOX (hbox), box);
|
||||
|
||||
label = gtk_label_new ("Dropdowns");
|
||||
gtk_widget_add_css_class (label, "title-4");
|
||||
gtk_box_append (GTK_BOX (box), label);
|
||||
|
||||
/* A basic dropdown */
|
||||
button = drop_down_new_from_strings (times, NULL, NULL);
|
||||
gtk_box_append (GTK_BOX (box), button);
|
||||
|
||||
/* A dropdown using an expression to obtain strings */
|
||||
button = drop_down_new_from_strings (many_times, NULL, NULL);
|
||||
gtk_drop_down_set_enable_search (GTK_DROP_DOWN (button), TRUE);
|
||||
expression = gtk_cclosure_expression_new (G_TYPE_STRING, NULL,
|
||||
0, NULL,
|
||||
(GCallback)get_title,
|
||||
NULL, NULL);
|
||||
gtk_drop_down_set_expression (GTK_DROP_DOWN (button), expression);
|
||||
gtk_expression_unref (expression);
|
||||
gtk_box_append (GTK_BOX (box), button);
|
||||
|
||||
/* A dropdown using a non-trivial model, and search */
|
||||
button = gtk_drop_down_new ();
|
||||
|
||||
model = G_LIST_MODEL (pango_cairo_font_map_get_default ());
|
||||
@@ -270,30 +364,86 @@ do_dropdown (GtkWidget *do_widget)
|
||||
|
||||
spin = gtk_spin_button_new_with_range (-1, g_list_model_get_n_items (G_LIST_MODEL (model)), 1);
|
||||
gtk_widget_set_halign (spin, GTK_ALIGN_START);
|
||||
gtk_widget_set_margin_start (spin, 20);
|
||||
g_object_bind_property (button, "selected", spin, "value", G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
|
||||
gtk_box_append (GTK_BOX (box), spin);
|
||||
|
||||
check = gtk_check_button_new_with_label ("Enable search");
|
||||
gtk_widget_set_margin_start (check, 20);
|
||||
g_object_bind_property (button, "enable-search", check, "active", G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
|
||||
gtk_box_append (GTK_BOX (box), check);
|
||||
|
||||
g_object_unref (model);
|
||||
|
||||
button = drop_down_new_from_strings (times, NULL, NULL);
|
||||
gtk_box_append (GTK_BOX (box), button);
|
||||
|
||||
button = drop_down_new_from_strings (many_times, NULL, NULL);
|
||||
gtk_drop_down_set_enable_search (GTK_DROP_DOWN (button), TRUE);
|
||||
expression = gtk_cclosure_expression_new (G_TYPE_STRING, NULL,
|
||||
0, NULL,
|
||||
(GCallback)get_title,
|
||||
NULL, NULL);
|
||||
gtk_drop_down_set_expression (GTK_DROP_DOWN (button), expression);
|
||||
gtk_expression_unref (expression);
|
||||
gtk_box_append (GTK_BOX (box), button);
|
||||
|
||||
/* A dropdown with a separate list factory */
|
||||
button = drop_down_new_from_strings (device_titles, device_icons, device_descriptions);
|
||||
gtk_box_append (GTK_BOX (box), button);
|
||||
|
||||
gtk_box_append (GTK_BOX (hbox), gtk_separator_new (GTK_ORIENTATION_VERTICAL));
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
|
||||
gtk_box_append (GTK_BOX (hbox), box);
|
||||
|
||||
label = gtk_label_new ("Suggestions");
|
||||
gtk_widget_add_css_class (label, "title-4");
|
||||
gtk_box_append (GTK_BOX (box), label);
|
||||
|
||||
/* A basic suggestion entry */
|
||||
entry = gtk_suggestion_entry_new ();
|
||||
g_object_set (entry, "placeholder-text", "Words with T or G…", NULL);
|
||||
gtk_suggestion_entry_set_from_strings (GTK_SUGGESTION_ENTRY (entry), words);
|
||||
|
||||
gtk_box_append (GTK_BOX (box), entry);
|
||||
|
||||
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
|
||||
gtk_widget_set_halign (hbox, GTK_ALIGN_START);
|
||||
gtk_widget_set_margin_start (hbox, 20);
|
||||
spin = gtk_spin_button_new_with_range (0, 10, 1);
|
||||
g_object_bind_property (entry, "minimum-length", spin, "value", G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
|
||||
gtk_box_append (GTK_BOX (hbox), gtk_label_new ("Min. length"));
|
||||
gtk_box_append (GTK_BOX (hbox), spin);
|
||||
gtk_box_append (GTK_BOX (box), hbox);
|
||||
|
||||
check = gtk_check_button_new_with_label ("Auto-Insert");
|
||||
gtk_widget_set_margin_start (check, 20);
|
||||
g_object_bind_property (entry, "insert-prefix", check, "active", G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
|
||||
gtk_box_append (GTK_BOX (box), check);
|
||||
|
||||
check = gtk_check_button_new_with_label ("Auto-Select");
|
||||
gtk_widget_set_margin_start (check, 20);
|
||||
g_object_bind_property (entry, "insert-selection", check, "active", G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
|
||||
gtk_box_append (GTK_BOX (box), check);
|
||||
|
||||
/* A suggestion entry using a custom model, and no filtering */
|
||||
entry = gtk_suggestion_entry_new ();
|
||||
|
||||
cwd = g_get_current_dir ();
|
||||
file = g_file_new_for_path (cwd);
|
||||
dir = G_LIST_MODEL (gtk_directory_list_new ("standard::display-name,standard::content-type,standard::icon,standard::size", file));
|
||||
gtk_suggestion_entry_set_model (GTK_SUGGESTION_ENTRY (entry), dir);
|
||||
g_object_unref (dir);
|
||||
g_object_unref (file);
|
||||
g_free (cwd);
|
||||
|
||||
expression = gtk_cclosure_expression_new (G_TYPE_STRING, NULL,
|
||||
0, NULL,
|
||||
(GCallback)get_file_name,
|
||||
NULL, NULL);
|
||||
gtk_suggestion_entry_set_expression (GTK_SUGGESTION_ENTRY (entry), expression);
|
||||
gtk_expression_unref (expression);
|
||||
|
||||
factory = gtk_signal_list_item_factory_new ();
|
||||
g_signal_connect (factory, "setup", G_CALLBACK (setup_item), NULL);
|
||||
g_signal_connect (factory, "bind", G_CALLBACK (bind_item), NULL);
|
||||
|
||||
gtk_suggestion_entry_set_factory (GTK_SUGGESTION_ENTRY (entry), factory);
|
||||
g_object_unref (factory);
|
||||
|
||||
gtk_suggestion_entry_set_use_filter (GTK_SUGGESTION_ENTRY (entry), FALSE);
|
||||
gtk_suggestion_entry_set_show_button (GTK_SUGGESTION_ENTRY (entry), TRUE);
|
||||
gtk_suggestion_entry_set_insert_selection (GTK_SUGGESTION_ENTRY (entry), TRUE);
|
||||
|
||||
gtk_box_append (GTK_BOX (box), entry);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
<property name="default-height">400</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<style>
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
<property name="title">Font Explorer</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="reset">
|
||||
<property name="receives-default">1</property>
|
||||
|
||||
@@ -30,7 +30,6 @@ do_headerbar (GtkWidget *do_widget)
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
|
||||
|
||||
header = gtk_header_bar_new ();
|
||||
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), TRUE);
|
||||
|
||||
button = gtk_button_new ();
|
||||
icon = g_themed_icon_new ("mail-send-receive-symbolic");
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
<property name="default-height">500</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<style>
|
||||
|
||||
@@ -627,6 +627,23 @@ setup_listitem_cb (GtkListItemFactory *factory,
|
||||
gtk_expression_unref (color_expression);
|
||||
}
|
||||
|
||||
static void
|
||||
setup_selection_listitem_cb (GtkListItemFactory *factory,
|
||||
GtkListItem *list_item)
|
||||
{
|
||||
GtkWidget *picture;
|
||||
GtkExpression *color_expression, *expression;
|
||||
|
||||
expression = gtk_constant_expression_new (GTK_TYPE_LIST_ITEM, list_item);
|
||||
color_expression = gtk_property_expression_new (GTK_TYPE_LIST_ITEM, expression, "item");
|
||||
|
||||
picture = gtk_picture_new ();
|
||||
gtk_widget_set_size_request (picture, 8, 8);
|
||||
gtk_expression_bind (color_expression, picture, "paintable", NULL);
|
||||
|
||||
gtk_list_item_set_child (list_item, picture);
|
||||
}
|
||||
|
||||
static void
|
||||
set_title (gpointer item,
|
||||
const char *title)
|
||||
@@ -777,6 +794,47 @@ bind_number_item (GtkSignalListItemFactory *factory,
|
||||
g_free (string);
|
||||
}
|
||||
|
||||
static void
|
||||
update_selection_count (GListModel *model,
|
||||
guint position,
|
||||
guint removed,
|
||||
guint added,
|
||||
gpointer data)
|
||||
{
|
||||
char *text;
|
||||
text = g_strdup_printf ("%u", g_list_model_get_n_items (model));
|
||||
gtk_label_set_label (GTK_LABEL (data), text);
|
||||
g_free (text);
|
||||
}
|
||||
|
||||
static void
|
||||
update_selection_average (GListModel *model,
|
||||
guint position,
|
||||
guint removed,
|
||||
guint added,
|
||||
gpointer data)
|
||||
{
|
||||
guint n = g_list_model_get_n_items (model);
|
||||
GdkRGBA c = { 0, 0, 0, 1 };
|
||||
guint i;
|
||||
GtkColor *color;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
color = g_list_model_get_item (model, i);
|
||||
|
||||
c.red += color->color.red;
|
||||
c.green += color->color.green;
|
||||
c.blue += color->color.blue;
|
||||
|
||||
g_object_unref (color);
|
||||
}
|
||||
|
||||
color = gtk_color_new ("", c.red / n, c.green / n, c.blue / n);
|
||||
gtk_picture_set_paintable (GTK_PICTURE (data), GDK_PAINTABLE (color));
|
||||
g_object_unref (color);
|
||||
}
|
||||
|
||||
static GtkWidget *window = NULL;
|
||||
|
||||
GtkWidget *
|
||||
@@ -797,11 +855,26 @@ do_listview_colors (GtkWidget *do_widget)
|
||||
PangoAttrList *attrs;
|
||||
char *string;
|
||||
guint len;
|
||||
GtkWidget *selection_view;
|
||||
GListModel *selection_filter;
|
||||
GListModel *no_selection;
|
||||
GtkWidget *grid;
|
||||
GtkWidget *selection_size_label;
|
||||
GtkWidget *selection_average_picture;
|
||||
GtkWidget *selection_info_toggle;
|
||||
GtkWidget *selection_info_revealer;
|
||||
GtkCssProvider *provider;
|
||||
|
||||
provider = gtk_css_provider_new ();
|
||||
gtk_css_provider_load_from_resource (provider, "/listview_colors/listview_colors.css");
|
||||
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
|
||||
GTK_STYLE_PROVIDER (provider),
|
||||
800);
|
||||
g_object_unref (provider);
|
||||
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Colors");
|
||||
header = gtk_header_bar_new ();
|
||||
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), TRUE);
|
||||
gtk_window_set_titlebar (GTK_WINDOW (window), header);
|
||||
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
|
||||
@@ -809,14 +882,85 @@ do_listview_colors (GtkWidget *do_widget)
|
||||
gtk_widget_get_display (do_widget));
|
||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer*)&window);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
gtk_window_set_child (GTK_WINDOW (window), box);
|
||||
|
||||
selection_info_revealer = gtk_revealer_new ();
|
||||
gtk_box_append (GTK_BOX (box), selection_info_revealer);
|
||||
|
||||
grid = gtk_grid_new ();
|
||||
gtk_revealer_set_child (GTK_REVEALER (selection_info_revealer), grid);
|
||||
gtk_widget_set_margin_start (grid, 10);
|
||||
gtk_widget_set_margin_end (grid, 10);
|
||||
gtk_widget_set_margin_top (grid, 10);
|
||||
gtk_widget_set_margin_bottom (grid, 10);
|
||||
gtk_grid_set_row_spacing (GTK_GRID (grid), 10);
|
||||
gtk_grid_set_column_spacing (GTK_GRID (grid), 10);
|
||||
|
||||
label = gtk_label_new ("Selection");
|
||||
gtk_widget_set_hexpand (label, TRUE);
|
||||
gtk_widget_add_css_class (label, "title-3");
|
||||
gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 5, 1);
|
||||
|
||||
gtk_grid_attach (GTK_GRID (grid), gtk_label_new ("Size:"), 0, 2, 1, 1);
|
||||
|
||||
selection_size_label = gtk_label_new ("0");
|
||||
gtk_grid_attach (GTK_GRID (grid), selection_size_label, 1, 2, 1, 1);
|
||||
|
||||
gtk_grid_attach (GTK_GRID (grid), gtk_label_new ("Average:"), 2, 2, 1, 1);
|
||||
|
||||
selection_average_picture = gtk_picture_new ();
|
||||
gtk_widget_set_size_request (selection_average_picture, 32, 32);
|
||||
gtk_grid_attach (GTK_GRID (grid), selection_average_picture, 3, 2, 1, 1);
|
||||
|
||||
label = gtk_label_new ("");
|
||||
gtk_widget_set_hexpand (label, TRUE);
|
||||
gtk_grid_attach (GTK_GRID (grid), label, 4, 2, 1, 1);
|
||||
|
||||
sw = gtk_scrolled_window_new ();
|
||||
gtk_window_set_child (GTK_WINDOW (window), sw);
|
||||
gtk_widget_set_hexpand (sw, TRUE);
|
||||
|
||||
gtk_grid_attach (GTK_GRID (grid), sw, 0, 1, 5, 1);
|
||||
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
|
||||
GTK_POLICY_NEVER,
|
||||
GTK_POLICY_AUTOMATIC);
|
||||
|
||||
factory = gtk_signal_list_item_factory_new ();
|
||||
g_signal_connect (factory, "setup", G_CALLBACK (setup_selection_listitem_cb), NULL);
|
||||
selection_view = gtk_grid_view_new_with_factory (factory);
|
||||
gtk_widget_add_css_class (selection_view, "compact");
|
||||
gtk_grid_view_set_max_columns (GTK_GRID_VIEW (selection_view), 200);
|
||||
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), selection_view);
|
||||
|
||||
sw = gtk_scrolled_window_new ();
|
||||
gtk_box_append (GTK_BOX (box), sw);
|
||||
|
||||
gridview = create_color_grid ();
|
||||
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), gridview);
|
||||
gtk_widget_set_hexpand (sw, TRUE);
|
||||
gtk_widget_set_vexpand (sw, TRUE);
|
||||
model = gtk_grid_view_get_model (GTK_GRID_VIEW (gridview));
|
||||
|
||||
selection_filter = G_LIST_MODEL (gtk_selection_filter_model_new (GTK_SELECTION_MODEL (model)));
|
||||
g_signal_connect (selection_filter, "items-changed", G_CALLBACK (update_selection_count), selection_size_label);
|
||||
g_signal_connect (selection_filter, "items-changed", G_CALLBACK (update_selection_average), selection_average_picture);
|
||||
|
||||
no_selection = G_LIST_MODEL (gtk_no_selection_new (selection_filter));
|
||||
gtk_grid_view_set_model (GTK_GRID_VIEW (selection_view), no_selection);
|
||||
g_object_unref (selection_filter);
|
||||
g_object_unref (no_selection);
|
||||
|
||||
g_object_get (model, "model", &model, NULL);
|
||||
|
||||
selection_info_toggle = gtk_toggle_button_new ();
|
||||
gtk_button_set_icon_name (GTK_BUTTON (selection_info_toggle), "emblem-important-symbolic");
|
||||
gtk_widget_set_tooltip_text (selection_info_toggle, "Show selection info");
|
||||
gtk_header_bar_pack_start (GTK_HEADER_BAR (header), selection_info_toggle);
|
||||
|
||||
g_object_bind_property (selection_info_toggle, "active",
|
||||
selection_info_revealer, "reveal-child",
|
||||
G_BINDING_DEFAULT);
|
||||
|
||||
button = gtk_button_new_with_mnemonic ("_Refill");
|
||||
g_signal_connect (button, "clicked",
|
||||
G_CALLBACK (refill),
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
.view.compact > child {
|
||||
padding: 1px;
|
||||
}
|
||||
@@ -174,7 +174,6 @@
|
||||
<property name="default-height">400</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="icon-name">go-up-symbolic</property>
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
<property name="title" translatable="yes">Minesweeper</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="label">New Game</property>
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
<property name="default-height">480</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child type="end">
|
||||
<object class="GtkToggleButton" id="search_button">
|
||||
<property name="icon-name">system-search-symbolic</property>
|
||||
|
||||
@@ -194,8 +194,8 @@ create_weather_model (void)
|
||||
}
|
||||
|
||||
static void
|
||||
setup_widget (GtkListItem *list_item,
|
||||
gpointer unused)
|
||||
setup_widget (GtkSignalListItemFactory *factory,
|
||||
GtkListItem *list_item)
|
||||
{
|
||||
GtkWidget *box, *child;
|
||||
|
||||
@@ -218,8 +218,8 @@ setup_widget (GtkListItem *list_item,
|
||||
}
|
||||
|
||||
static void
|
||||
bind_widget (GtkListItem *list_item,
|
||||
gpointer unused)
|
||||
bind_widget (GtkSignalListItemFactory *factory,
|
||||
GtkListItem *list_item)
|
||||
{
|
||||
GtkWidget *box, *child;
|
||||
GtkWeatherInfo *info;
|
||||
@@ -282,11 +282,12 @@ create_weather_view (void)
|
||||
{
|
||||
GtkWidget *listview;
|
||||
GListModel *model, *selection;
|
||||
GtkListItemFactory *factory;
|
||||
|
||||
listview = gtk_list_view_new_with_factory (
|
||||
gtk_functions_list_item_factory_new (setup_widget,
|
||||
bind_widget,
|
||||
NULL, NULL));
|
||||
factory = gtk_signal_list_item_factory_new ();
|
||||
g_signal_connect (factory, "setup", G_CALLBACK (setup_widget), NULL);
|
||||
g_signal_connect (factory, "bind", G_CALLBACK (bind_widget), NULL);
|
||||
listview = gtk_list_view_new_with_factory (factory);
|
||||
gtk_orientable_set_orientation (GTK_ORIENTABLE (listview), GTK_ORIENTATION_HORIZONTAL);
|
||||
gtk_list_view_set_show_separators (GTK_LIST_VIEW (listview), TRUE);
|
||||
model = create_weather_model ();
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
<property name="default-height">600</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="headerbar">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="valign">center</property>
|
||||
|
||||
@@ -69,7 +69,6 @@ do_markup (GtkWidget *do_widget)
|
||||
g_signal_connect (show_source, "toggled", G_CALLBACK (source_toggled), stack);
|
||||
|
||||
header = gtk_header_bar_new ();
|
||||
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), TRUE);
|
||||
gtk_header_bar_pack_start (GTK_HEADER_BAR (header), show_source);
|
||||
gtk_window_set_titlebar (GTK_WINDOW (window), header);
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ demos = files([
|
||||
'cursors.c',
|
||||
'dialog.c',
|
||||
'drawingarea.c',
|
||||
'dropdown.c',
|
||||
'dnd.c',
|
||||
'editable_cells.c',
|
||||
'entry_completion.c',
|
||||
@@ -47,6 +46,7 @@ demos = files([
|
||||
'listview_colors.c',
|
||||
'listview_filebrowser.c',
|
||||
'listview_minesweeper.c',
|
||||
'dropdown.c',
|
||||
'listview_settings.c',
|
||||
'listview_weather.c',
|
||||
'listview_words.c',
|
||||
|
||||
@@ -4,9 +4,7 @@
|
||||
<property name="title" translatable="yes">Model Button</property>
|
||||
<property name="resizable">0</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar">
|
||||
<property name="show-title-buttons">1</property>
|
||||
</object>
|
||||
<object class="GtkHeaderBar"/>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
|
||||
@@ -392,7 +392,6 @@ do_paint (GtkWidget *toplevel)
|
||||
gtk_window_set_child (GTK_WINDOW (window), draw_area);
|
||||
|
||||
headerbar = gtk_header_bar_new ();
|
||||
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (headerbar), TRUE);
|
||||
|
||||
colorbutton = gtk_color_button_new ();
|
||||
g_signal_connect (colorbutton, "color-set",
|
||||
|
||||
@@ -276,7 +276,6 @@ do_peg_solitaire (GtkWidget *do_widget)
|
||||
g_signal_connect (restart, "clicked", G_CALLBACK (restart), NULL);
|
||||
|
||||
header = gtk_header_bar_new ();
|
||||
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), TRUE);
|
||||
gtk_header_bar_pack_start (GTK_HEADER_BAR (header), restart);
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
|
||||
@@ -40,7 +40,6 @@ do_sidebar (GtkWidget *do_widget)
|
||||
gtk_widget_set_size_request (window, 500, 350);
|
||||
|
||||
header = gtk_header_bar_new ();
|
||||
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR(header), TRUE);
|
||||
gtk_window_set_titlebar (GTK_WINDOW(window), header);
|
||||
gtk_window_set_title (GTK_WINDOW(window), "Stack Sidebar");
|
||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
|
||||
|
||||
@@ -470,7 +470,6 @@ do_sliding_puzzle (GtkWidget *do_widget)
|
||||
g_signal_connect (restart, "clicked", G_CALLBACK (reshuffle), NULL);
|
||||
|
||||
header = gtk_header_bar_new ();
|
||||
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), TRUE);
|
||||
gtk_header_bar_pack_start (GTK_HEADER_BAR (header), restart);
|
||||
gtk_header_bar_pack_end (GTK_HEADER_BAR (header), tweak);
|
||||
window = gtk_window_new ();
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
<property name="resizable">0</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child type="start">
|
||||
<object class="GtkToggleButton" id="toggle">
|
||||
<property name="label">Cycle</property>
|
||||
|
||||
@@ -73,7 +73,6 @@ do_video_player (GtkWidget *do_widget)
|
||||
gtk_window_set_child (GTK_WINDOW (window), video);
|
||||
|
||||
title = gtk_header_bar_new ();
|
||||
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (title), TRUE);
|
||||
gtk_window_set_titlebar (GTK_WINDOW (window), title);
|
||||
|
||||
open_button = gtk_button_new_with_mnemonic ("_Open");
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<property name="default-height">768</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child type="title">
|
||||
<object class="GtkBox">
|
||||
<style>
|
||||
|
||||
@@ -103,7 +103,6 @@
|
||||
<property name="focus-widget">text_view</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child type="start">
|
||||
<object class="GtkButton">
|
||||
<property name="icon-name">document-open-symbolic</property>
|
||||
|
||||
@@ -436,7 +436,6 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
|
||||
<property name="title">GTK Widget Factory</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="headerbar1">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child type="title">
|
||||
<object class="GtkStackSwitcher" id="stack_switcher">
|
||||
<property name="stack">toplevel_stack</property>
|
||||
|
||||
@@ -1423,7 +1423,6 @@ the search bar below the header bar.
|
||||
<property name="default-height">400</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child type="title">
|
||||
<object class="GtkStackSwitcher" id="tabs">
|
||||
<property name="stack">stack</property>
|
||||
@@ -1537,7 +1536,6 @@ GtkMenuButton, GtkRevealer and GtkListBox.
|
||||
<property name="default-height">400</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child type="title">
|
||||
<object class="GtkStackSwitcher" id="tabs">
|
||||
<property name="stack">stack</property>
|
||||
|
||||
@@ -54,8 +54,9 @@
|
||||
<section>
|
||||
<xi:include href="xml/gtkfilter.xml" />
|
||||
<xi:include href="xml/gtkcustomfilter.xml" />
|
||||
<xi:include href="xml/gtkstringfilter.xml" />
|
||||
<xi:include href="xml/gtkmultifilter.xml" />
|
||||
<xi:include href="xml/gtkstringfilter.xml" />
|
||||
<xi:include href="xml/gtkfilefilter.xml" />
|
||||
</section>
|
||||
<xi:include href="xml/gtkflattenlistmodel.xml" />
|
||||
<xi:include href="xml/gtkmaplistmodel.xml" />
|
||||
@@ -74,6 +75,7 @@
|
||||
<xi:include href="xml/gtksingleselection.xml" />
|
||||
<xi:include href="xml/gtkmultiselection.xml" />
|
||||
</section>
|
||||
<xi:include href="xml/gtkselectionfiltermodel.xml" />
|
||||
<xi:include href="xml/gtkbookmarklist.xml" />
|
||||
<xi:include href="xml/gtkdirectorylist.xml" />
|
||||
<xi:include href="xml/gtkstringlist.xml" />
|
||||
@@ -219,6 +221,7 @@
|
||||
<xi:include href="xml/gtksearchentry.xml" />
|
||||
<xi:include href="xml/gtksearchbar.xml" />
|
||||
<xi:include href="xml/gtkeditablelabel.xml" />
|
||||
<xi:include href="xml/gtksuggestionentry.xml" />
|
||||
</chapter>
|
||||
|
||||
<chapter id="TextWidgetObjects">
|
||||
@@ -284,7 +287,6 @@
|
||||
<xi:include href="xml/gtkfilechoosernative.xml" />
|
||||
<xi:include href="xml/gtkfilechooserdialog.xml" />
|
||||
<xi:include href="xml/gtkfilechooserwidget.xml" />
|
||||
<xi:include href="xml/gtkfilefilter.xml" />
|
||||
<xi:include href="xml/gtkfontchooser.xml" />
|
||||
<xi:include href="xml/gtkfontbutton.xml" />
|
||||
<xi:include href="xml/gtkfontchooserwidget.xml" />
|
||||
|
||||
@@ -375,7 +375,7 @@ gtk_bitset_subtract
|
||||
gtk_bitset_difference
|
||||
gtk_bitset_shift_left
|
||||
gtk_bitset_shift_right
|
||||
gtk_bitset_slice
|
||||
gtk_bitset_splice
|
||||
<SUBSECTION>
|
||||
GtkBitsetIter
|
||||
gtk_bitset_iter_init_first
|
||||
@@ -423,6 +423,7 @@ gtk_selection_model_get_type
|
||||
GtkNoSelection
|
||||
gtk_no_selection_new
|
||||
gtk_no_selection_get_model
|
||||
gtk_no_selection_set_model
|
||||
<SUBSECTION Private>
|
||||
gtk_no_selection_get_type
|
||||
</SECTION>
|
||||
@@ -434,6 +435,7 @@ GtkSingleSelection
|
||||
GTK_INVALID_LIST_POSITION
|
||||
gtk_single_selection_new
|
||||
gtk_single_selection_get_model
|
||||
gtk_single_selection_set_model
|
||||
gtk_single_selection_get_selected
|
||||
gtk_single_selection_set_selected
|
||||
gtk_single_selection_get_selected_item
|
||||
@@ -450,6 +452,8 @@ gtk_single_selection_get_type
|
||||
<TITLE>GtkMultiSeledction</TITLE>
|
||||
GtkMultiSelection
|
||||
gtk_multi_selection_new
|
||||
gtk_multi_selection_get_model
|
||||
gtk_multi_selection_set_model
|
||||
<SUBSECTION Private>
|
||||
gtk_multi_selection_get_type
|
||||
</SECTION>
|
||||
@@ -1296,23 +1300,19 @@ gtk_file_chooser_get_current_name
|
||||
<SUBSECTION>
|
||||
gtk_file_chooser_get_file
|
||||
gtk_file_chooser_set_file
|
||||
gtk_file_chooser_select_file
|
||||
gtk_file_chooser_unselect_file
|
||||
gtk_file_chooser_select_all
|
||||
gtk_file_chooser_unselect_all
|
||||
gtk_file_chooser_get_files
|
||||
gtk_file_chooser_set_current_folder
|
||||
gtk_file_chooser_get_current_folder
|
||||
<SUBSECTION>
|
||||
gtk_file_chooser_add_filter
|
||||
gtk_file_chooser_remove_filter
|
||||
gtk_file_chooser_list_filters
|
||||
gtk_file_chooser_get_filters
|
||||
gtk_file_chooser_set_filter
|
||||
gtk_file_chooser_get_filter
|
||||
<SUBSECTION>
|
||||
gtk_file_chooser_add_shortcut_folder
|
||||
gtk_file_chooser_remove_shortcut_folder
|
||||
gtk_file_chooser_list_shortcut_folders
|
||||
gtk_file_chooser_get_shortcut_folders
|
||||
<SUBSECTION>
|
||||
gtk_file_chooser_add_choice
|
||||
gtk_file_chooser_remove_choice
|
||||
@@ -1409,18 +1409,13 @@ GtkFileChooserButtonPrivate
|
||||
<SECTION>
|
||||
<FILE>gtkfilefilter</FILE>
|
||||
GtkFileFilter
|
||||
GtkFileFilterInfo
|
||||
GtkFileFilterFlags
|
||||
GtkFileFilterFunc
|
||||
gtk_file_filter_new
|
||||
gtk_file_filter_set_name
|
||||
gtk_file_filter_get_name
|
||||
gtk_file_filter_add_mime_type
|
||||
gtk_file_filter_add_pattern
|
||||
gtk_file_filter_add_pixbuf_formats
|
||||
gtk_file_filter_add_custom
|
||||
gtk_file_filter_get_needed
|
||||
gtk_file_filter_filter
|
||||
gtk_file_filter_get_attributes
|
||||
|
||||
<SUBSECTION Serialization>
|
||||
gtk_file_filter_new_from_gvariant
|
||||
@@ -1445,6 +1440,8 @@ gtk_directory_list_get_file
|
||||
gtk_directory_list_set_file
|
||||
gtk_directory_list_get_io_priority
|
||||
gtk_directory_list_set_io_priority
|
||||
gtk_directory_list_get_monitored
|
||||
gtk_directory_list_set_monitored
|
||||
gtk_directory_list_is_loading
|
||||
gtk_directory_list_get_error
|
||||
<SUBSECTION Standard>
|
||||
@@ -1539,7 +1536,6 @@ gtk_custom_filter_get_type
|
||||
<TITLE>GtkFilterListModel</TITLE>
|
||||
GtkFilterListModel
|
||||
gtk_filter_list_model_new
|
||||
gtk_filter_list_model_new_for_type
|
||||
gtk_filter_list_model_set_model
|
||||
gtk_filter_list_model_get_model
|
||||
gtk_filter_list_model_set_filter
|
||||
@@ -2701,7 +2697,6 @@ gtk_size_group_get_type
|
||||
<TITLE>GtkSliceListModel</TITLE>
|
||||
GtkSliceListModel
|
||||
gtk_slice_list_model_new
|
||||
gtk_slice_list_model_new_for_type
|
||||
gtk_slice_list_model_set_model
|
||||
gtk_slice_list_model_get_model
|
||||
gtk_slice_list_model_set_offset
|
||||
@@ -2833,7 +2828,6 @@ gtk_tree_list_row_sorter_get_type
|
||||
<TITLE>GtkSortListModel</TITLE>
|
||||
GtkSortListModel
|
||||
gtk_sort_list_model_new
|
||||
gtk_sort_list_model_new_for_type
|
||||
gtk_sort_list_model_set_sorter
|
||||
gtk_sort_list_model_get_sorter
|
||||
gtk_sort_list_model_set_model
|
||||
@@ -7613,6 +7607,42 @@ gtk_string_list_take
|
||||
gtk_string_list_remove
|
||||
gtk_string_list_splice
|
||||
gtk_string_list_get_string
|
||||
<SUBSECTION>
|
||||
GtkStringObject
|
||||
gtk_string_object_new
|
||||
gtk_string_object_get_string
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkselectionfiltermodel</FILE>
|
||||
<TITLE>GtkSelectionFilterModel</TITLE>
|
||||
GtkSelectionFilterModel
|
||||
gtk_selection_filter_model_new
|
||||
gtk_selection_filter_model_new_for_type
|
||||
gtk_selection_filter_model_set_model
|
||||
gtk_selection_filter_model_get_model
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtksuggestionentry</FILE>
|
||||
<TITLE>GtkSuggestionEntry</TITLE>
|
||||
GtkSuggestionEntry
|
||||
gtk_suggestion_entry_new
|
||||
gtk_suggestion_entry_set_model
|
||||
gtk_suggestion_entry_get_model
|
||||
gtk_suggestion_entry_set_from_strings
|
||||
gtk_suggestion_entry_set_factory
|
||||
gtk_suggestion_entry_get_factory
|
||||
gtk_suggestion_entry_set_expression
|
||||
gtk_suggestion_entry_get_expression
|
||||
gtk_suggestion_entry_set_use_filter
|
||||
gtk_suggestion_entry_get_use_filter
|
||||
gtk_suggestion_entry_set_insert_selection
|
||||
gtk_suggestion_entry_get_insert_selection
|
||||
gtk_suggestion_entry_set_insert_prefix
|
||||
gtk_suggestion_entry_get_insert_prefix
|
||||
gtk_suggestion_entry_set_show_button
|
||||
gtk_suggestion_entry_get_show_button
|
||||
gtk_suggestion_entry_set_minimum_length
|
||||
gtk_suggestion_entry_get_minimum_length
|
||||
</SECTION>
|
||||
|
||||
@@ -184,6 +184,7 @@ gtk_scrollbar_get_type
|
||||
gtk_scrolled_window_get_type
|
||||
gtk_search_bar_get_type
|
||||
gtk_search_entry_get_type
|
||||
gtk_selection_filter_model_get_type
|
||||
gtk_selection_model_get_type
|
||||
gtk_separator_get_type
|
||||
gtk_settings_get_type
|
||||
@@ -213,6 +214,7 @@ gtk_string_filter_get_type
|
||||
gtk_string_list_get_type
|
||||
gtk_string_object_get_type
|
||||
gtk_string_sorter_get_type
|
||||
gtk_suggestion_entry_get_type
|
||||
gtk_switch_get_type
|
||||
gtk_level_bar_get_type
|
||||
gtk_style_context_get_type
|
||||
|
||||
@@ -411,6 +411,7 @@ and gtk_box_append(). You can also reorder box children as necessary.
|
||||
The gtk_header_bar_set_show_close_button() function has been renamed to
|
||||
the more accurate name gtk_header_bar_set_show_title_buttons(). The
|
||||
corresponding getter and the property itself have also been renamed.
|
||||
The default value of the property is now %TRUE instead of %FALSE.
|
||||
|
||||
The gtk_header_bar_set_custom_title() function has been renamed to
|
||||
the more accurate name gtk_header_bar_set_title_widget(). The
|
||||
|
||||
@@ -198,4 +198,6 @@ transitioning code for easy lookup:
|
||||
| #GtkCellLayout | #GtkListItemFactory |
|
||||
| #GtkCellArea | #GtkWidget |
|
||||
| #GtkCellRenderer | #GtkWidget |
|
||||
| #GtkComboBoxText | #GtkSuggestionEntry |
|
||||
| #GtkEntryCompletion | #GtkSuggestionEntry |
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
<property name="default-height">400</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child type="title">
|
||||
<object class="GtkStackSwitcher" id="tabs">
|
||||
<property name="stack">stack</property>
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
<property name="default-height">400</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child type="title">
|
||||
<object class="GtkStackSwitcher" id="tabs">
|
||||
<property name="stack">stack</property>
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
<property name="default-height">400</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child type="title">
|
||||
<object class="GtkStackSwitcher" id="tabs">
|
||||
<property name="stack">stack</property>
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
<property name="default-height">400</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child type="title">
|
||||
<object class="GtkStackSwitcher" id="tabs">
|
||||
<property name="stack">stack</property>
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
<property name="default-height">400</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child type="title">
|
||||
<object class="GtkStackSwitcher" id="tabs">
|
||||
<property name="stack">stack</property>
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
<property name="default-height">400</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child type="title">
|
||||
<object class="GtkStackSwitcher" id="tabs">
|
||||
<property name="stack">stack</property>
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
<property name="default-height">400</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="lines_label">
|
||||
<property name="visible">0</property>
|
||||
|
||||
@@ -15,7 +15,6 @@ new_window (GApplication *app,
|
||||
gtk_window_set_icon_name (GTK_WINDOW (window), "sunny");
|
||||
|
||||
header = gtk_header_bar_new ();
|
||||
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), TRUE);
|
||||
gtk_window_set_titlebar (GTK_WINDOW (window), header);
|
||||
|
||||
overlay = gtk_overlay_new ();
|
||||
|
||||
@@ -1648,6 +1648,38 @@ create_zxdg_toplevel_v6_resources (GdkSurface *surface)
|
||||
surface);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_wayland_surface_set_application_id (GdkSurface *surface, const char* application_id)
|
||||
{
|
||||
GdkWaylandSurface *impl;
|
||||
GdkWaylandDisplay *display_wayland;
|
||||
|
||||
g_return_if_fail (application_id != NULL);
|
||||
|
||||
if (GDK_SURFACE_DESTROYED (surface))
|
||||
return;
|
||||
|
||||
if (!is_realized_toplevel (surface))
|
||||
return;
|
||||
|
||||
display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
|
||||
impl = GDK_WAYLAND_SURFACE (surface);
|
||||
|
||||
switch (display_wayland->shell_variant)
|
||||
{
|
||||
case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
|
||||
xdg_toplevel_set_app_id (impl->display_server.xdg_toplevel,
|
||||
application_id);
|
||||
break;
|
||||
case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
|
||||
zxdg_toplevel_v6_set_app_id (impl->display_server.zxdg_toplevel_v6,
|
||||
application_id);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_surface_create_xdg_toplevel (GdkSurface *surface)
|
||||
{
|
||||
@@ -1702,19 +1734,7 @@ gdk_wayland_surface_create_xdg_toplevel (GdkSurface *surface)
|
||||
if (app_id == NULL)
|
||||
app_id = "GTK+ Application";
|
||||
|
||||
switch (display_wayland->shell_variant)
|
||||
{
|
||||
case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
|
||||
xdg_toplevel_set_app_id (impl->display_server.xdg_toplevel,
|
||||
app_id);
|
||||
break;
|
||||
case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6:
|
||||
zxdg_toplevel_v6_set_app_id (impl->display_server.zxdg_toplevel_v6,
|
||||
app_id);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
gdk_wayland_surface_set_application_id (surface, app_id);
|
||||
|
||||
maybe_set_gtk_surface_dbus_properties (surface);
|
||||
maybe_set_gtk_surface_modal (surface);
|
||||
|
||||
@@ -74,6 +74,10 @@ GDK_AVAILABLE_IN_ALL
|
||||
gboolean gdk_wayland_surface_set_transient_for_exported (GdkSurface *surface,
|
||||
char *parent_handle_str);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_wayland_surface_set_application_id (GdkSurface *surface,
|
||||
const char *application_id);
|
||||
|
||||
void gdk_wayland_surface_announce_csd (GdkSurface *surface);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
@@ -653,6 +653,8 @@ gdk_x11_clipboard_store_async (GdkClipboard *clipboard,
|
||||
GDK_DISPLAY_NOTE (display, CLIPBOARD,
|
||||
g_printerr ("%s: X error during ConvertSelection() while storing selection: %d\n", cb->selection, error));
|
||||
}
|
||||
|
||||
g_free (atoms);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
||||
@@ -1874,6 +1874,7 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
|
||||
case XI_Leave:
|
||||
{
|
||||
XIEnterEvent *xev = (XIEnterEvent *) ev;
|
||||
GdkModifierType state;
|
||||
|
||||
GDK_DISPLAY_NOTE (display, EVENTS,
|
||||
g_message ("%s notify:\twindow %ld\n\tsubwindow:%ld\n"
|
||||
@@ -1890,6 +1891,18 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
|
||||
source_device = g_hash_table_lookup (device_manager->id_table,
|
||||
GUINT_TO_POINTER (xev->sourceid));
|
||||
|
||||
state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
|
||||
|
||||
/* Ignore normal crossing events while there is an implicit grab.
|
||||
* We will receive a crossing event with one of the other details if
|
||||
* the implicit grab were finished (eg. releasing the button outside
|
||||
* the window triggers a XINotifyUngrab leave).
|
||||
*/
|
||||
if (xev->mode == XINotifyNormal &&
|
||||
(state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK |
|
||||
GDK_BUTTON4_MASK | GDK_BUTTON5_MASK)))
|
||||
break;
|
||||
|
||||
if (ev->evtype == XI_Enter &&
|
||||
xev->detail != XINotifyInferior && xev->mode != XINotifyPassiveUngrab &&
|
||||
GDK_IS_TOPLEVEL (surface))
|
||||
@@ -1916,12 +1929,11 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
|
||||
device,
|
||||
source_device,
|
||||
xev->time,
|
||||
_gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group),
|
||||
state,
|
||||
(double) xev->event_x / scale,
|
||||
(double) xev->event_y / scale,
|
||||
translate_crossing_mode (xev->mode),
|
||||
translate_notify_type (xev->detail));
|
||||
|
||||
}
|
||||
break;
|
||||
case XI_FocusIn:
|
||||
|
||||
@@ -1184,7 +1184,7 @@ _gdk_wm_protocols_filter (const XEvent *xevent,
|
||||
if (timings)
|
||||
timings->drawn_time = frame_drawn_time;
|
||||
|
||||
if (surface_impl->toplevel->frame_pending)
|
||||
if (!surface_impl->toplevel->frame_still_painting && surface_impl->toplevel->frame_pending)
|
||||
{
|
||||
surface_impl->toplevel->frame_pending = FALSE;
|
||||
gdk_surface_thaw_updates (win);
|
||||
|
||||
+49
-10
@@ -582,6 +582,23 @@ create_legacy_context (GdkDisplay *display,
|
||||
}
|
||||
|
||||
#ifdef HAVE_XDAMAGE
|
||||
static void
|
||||
finish_frame (GdkGLContext *context)
|
||||
{
|
||||
GdkX11GLContext *context_x11 = GDK_X11_GL_CONTEXT (context);
|
||||
GdkSurface *surface = gdk_gl_context_get_surface (context);
|
||||
|
||||
if (context_x11->xdamage == 0)
|
||||
return;
|
||||
|
||||
if (context_x11->frame_fence == 0)
|
||||
return;
|
||||
|
||||
glDeleteSync (context_x11->frame_fence);
|
||||
context_x11->frame_fence = 0;
|
||||
_gdk_x11_surface_set_frame_still_painting (surface, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
bind_context_for_frame_fence (GdkGLContext *context)
|
||||
{
|
||||
@@ -628,7 +645,6 @@ on_gl_surface_xevent (GdkGLContext *context,
|
||||
GdkX11Display *display_x11)
|
||||
{
|
||||
GdkX11GLContext *context_x11 = GDK_X11_GL_CONTEXT (context);
|
||||
GdkSurface *surface = gdk_gl_context_get_surface (context);
|
||||
XDamageNotifyEvent *damage_xevent;
|
||||
|
||||
if (!context_x11->is_attached)
|
||||
@@ -675,9 +691,7 @@ on_gl_surface_xevent (GdkGLContext *context,
|
||||
case GL_WAIT_FAILED:
|
||||
if (wait_result == GL_WAIT_FAILED)
|
||||
g_warning ("failed to wait on GL fence associated with last swap buffers call");
|
||||
glDeleteSync (context_x11->frame_fence);
|
||||
context_x11->frame_fence = 0;
|
||||
_gdk_x11_surface_set_frame_still_painting (surface, FALSE);
|
||||
finish_frame (context);
|
||||
break;
|
||||
|
||||
/* We assume that if the fence hasn't been signaled, that this
|
||||
@@ -696,6 +710,21 @@ on_gl_surface_xevent (GdkGLContext *context,
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
on_surface_state_changed (GdkGLContext *context)
|
||||
{
|
||||
GdkSurface *surface = gdk_gl_context_get_surface (context);
|
||||
|
||||
if ((surface->state & GDK_SURFACE_STATE_WITHDRAWN) == 0)
|
||||
return;
|
||||
|
||||
/* If we're about to withdraw the surface, then we don't care if the frame is
|
||||
* still getting rendered by the GPU. The compositor is going to remove the surface
|
||||
* from the scene anyway, so wrap up the frame.
|
||||
*/
|
||||
finish_frame (context);
|
||||
}
|
||||
#endif
|
||||
|
||||
static gboolean
|
||||
@@ -878,13 +907,23 @@ gdk_x11_gl_context_realize (GdkGLContext *context,
|
||||
gdk_x11_surface_get_xid (surface),
|
||||
XDamageReportRawRectangles);
|
||||
if (gdk_x11_display_error_trap_pop (display))
|
||||
context_x11->xdamage = 0;
|
||||
{
|
||||
context_x11->xdamage = 0;
|
||||
}
|
||||
else
|
||||
g_signal_connect_object (G_OBJECT (display),
|
||||
"xevent",
|
||||
G_CALLBACK (on_gl_surface_xevent),
|
||||
context,
|
||||
G_CONNECT_SWAPPED);
|
||||
{
|
||||
g_signal_connect_object (G_OBJECT (display),
|
||||
"xevent",
|
||||
G_CALLBACK (on_gl_surface_xevent),
|
||||
context,
|
||||
G_CONNECT_SWAPPED);
|
||||
g_signal_connect_object (G_OBJECT (surface),
|
||||
"notify::state",
|
||||
G_CALLBACK (on_surface_state_changed),
|
||||
context,
|
||||
G_CONNECT_SWAPPED);
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
+16
-6
@@ -2241,12 +2241,23 @@ render_cross_fade_node (GskGLRenderer *self,
|
||||
{
|
||||
GskRenderNode *start_node = gsk_cross_fade_node_get_start_child (node);
|
||||
GskRenderNode *end_node = gsk_cross_fade_node_get_end_child (node);
|
||||
float progress = gsk_cross_fade_node_get_progress (node);
|
||||
const float progress = gsk_cross_fade_node_get_progress (node);
|
||||
TextureRegion start_region;
|
||||
TextureRegion end_region;
|
||||
gboolean is_offscreen1, is_offscreen2;
|
||||
OpCrossFade *op;
|
||||
|
||||
if (progress <= 0)
|
||||
{
|
||||
gsk_gl_renderer_add_render_ops (self, start_node, builder);
|
||||
return;
|
||||
}
|
||||
else if (progress >= 1)
|
||||
{
|
||||
gsk_gl_renderer_add_render_ops (self, end_node, builder);
|
||||
return;
|
||||
}
|
||||
|
||||
/* TODO: We create 2 textures here as big as the cross-fade node, but both the
|
||||
* start and the end node might be a lot smaller than that. */
|
||||
|
||||
@@ -2266,11 +2277,10 @@ render_cross_fade_node (GskGLRenderer *self,
|
||||
&end_region, &is_offscreen2,
|
||||
FORCE_OFFSCREEN | RESET_CLIP | RESET_OPACITY))
|
||||
{
|
||||
load_vertex_data_with_region (ops_draw (builder, NULL),
|
||||
node,
|
||||
builder,
|
||||
&start_region,
|
||||
TRUE);
|
||||
const float prev_opacity = ops_set_opacity (builder, builder->current_opacity * progress);
|
||||
gsk_gl_renderer_add_render_ops (self, start_node, builder);
|
||||
ops_set_opacity (builder, prev_opacity);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+19
-19
@@ -104,7 +104,7 @@ gsk_color_node_peek_color (GskRenderNode *node)
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_color_node_new:
|
||||
* gsk_color_node_new:
|
||||
* @rgba: a #GdkRGBA specifying a color
|
||||
* @bounds: the rectangle to render the color into
|
||||
*
|
||||
@@ -216,7 +216,7 @@ gsk_linear_gradient_node_diff (GskRenderNode *node1,
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
gsk_render_node_diff_impossible (node1, node2, region);
|
||||
}
|
||||
|
||||
@@ -1163,7 +1163,7 @@ gsk_inset_shadow_node_diff (GskRenderNode *node1,
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_inset_shadow_node_new:
|
||||
* gsk_inset_shadow_node_new:
|
||||
* @outline: outline of the region containing the shadow
|
||||
* @color: color of the shadow
|
||||
* @dx: horizontal offset of shadow
|
||||
@@ -1465,7 +1465,7 @@ gsk_outset_shadow_node_diff (GskRenderNode *node1,
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_outset_shadow_node_new:
|
||||
* gsk_outset_shadow_node_new:
|
||||
* @outline: outline of the region surrounded by shadow
|
||||
* @color: color of the shadow
|
||||
* @dx: horizontal offset of shadow
|
||||
@@ -1672,7 +1672,7 @@ gsk_cairo_node_peek_surface (GskRenderNode *node)
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_cairo_node_new:
|
||||
* gsk_cairo_node_new:
|
||||
* @bounds: the rectangle to render to
|
||||
*
|
||||
* Creates a #GskRenderNode that will render a cairo surface
|
||||
@@ -1982,7 +1982,7 @@ gsk_transform_node_draw (GskRenderNode *node,
|
||||
ctm.xy, ctm.yy,
|
||||
ctm.x0, ctm.y0));
|
||||
cairo_transform (cr, &ctm);
|
||||
|
||||
|
||||
gsk_render_node_draw (self->child, cr);
|
||||
}
|
||||
|
||||
@@ -2062,7 +2062,7 @@ gsk_transform_node_diff (GskRenderNode *node1,
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_transform_node_new:
|
||||
* gsk_transform_node_new:
|
||||
* @child: The node to transform
|
||||
* @transform: (transfer none): The transform to apply
|
||||
*
|
||||
@@ -2188,7 +2188,7 @@ gsk_opacity_node_diff (GskRenderNode *node1,
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_opacity_node_new:
|
||||
* gsk_opacity_node_new:
|
||||
* @child: The node to draw
|
||||
* @opacity: The opacity to apply
|
||||
*
|
||||
@@ -2380,7 +2380,7 @@ nope:
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_color_matrix_node_new:
|
||||
* gsk_color_matrix_node_new:
|
||||
* @child: The node to draw
|
||||
* @color_matrix: The matrix to apply
|
||||
* @color_offset: Values to add to the color
|
||||
@@ -2533,7 +2533,7 @@ gsk_repeat_node_draw (GskRenderNode *node,
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_repeat_node_new:
|
||||
* gsk_repeat_node_new:
|
||||
* @bounds: The bounds of the area to be painted
|
||||
* @child: The child to repeat
|
||||
* @child_bounds: (allow-none): The area of the child to repeat or %NULL to
|
||||
@@ -2670,7 +2670,7 @@ gsk_clip_node_diff (GskRenderNode *node1,
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_clip_node_new:
|
||||
* gsk_clip_node_new:
|
||||
* @child: The node to draw
|
||||
* @clip: The clip to apply
|
||||
*
|
||||
@@ -2800,7 +2800,7 @@ gsk_rounded_clip_node_diff (GskRenderNode *node1,
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_rounded_clip_node_new:
|
||||
* gsk_rounded_clip_node_new:
|
||||
* @child: The node to draw
|
||||
* @clip: The clip to apply
|
||||
*
|
||||
@@ -3013,7 +3013,7 @@ gsk_shadow_node_get_bounds (GskShadowNode *self,
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_shadow_node_new:
|
||||
* gsk_shadow_node_new:
|
||||
* @child: The node to draw
|
||||
* @shadows: (array length=n_shadows): The shadows to apply
|
||||
* @n_shadows: number of entries in the @shadows array
|
||||
@@ -3210,7 +3210,7 @@ gsk_blend_node_diff (GskRenderNode *node1,
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_blend_node_new:
|
||||
* gsk_blend_node_new:
|
||||
* @bottom: The bottom node to be drawn
|
||||
* @top: The node to be blended onto the @bottom node
|
||||
* @blend_mode: The blend mode to use
|
||||
@@ -3359,7 +3359,7 @@ gsk_cross_fade_node_diff (GskRenderNode *node1,
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_cross_fade_node_new:
|
||||
* gsk_cross_fade_node_new:
|
||||
* @start: The start node to be drawn
|
||||
* @end: The node to be cross_fadeed onto the @start node
|
||||
* @progress: How far the fade has progressed from start to end. The value will
|
||||
@@ -3549,7 +3549,7 @@ font_has_color_glyphs (const PangoFont *font)
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_text_node_new:
|
||||
* gsk_text_node_new:
|
||||
* @font: the #PangoFont containing the glyphs
|
||||
* @glyphs: the #PangoGlyphString to render
|
||||
* @color: the foreground color to render with
|
||||
@@ -3953,7 +3953,7 @@ gsk_blur_node_diff (GskRenderNode *node1,
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_blur_node_new:
|
||||
* gsk_blur_node_new:
|
||||
* @child: the child node to blur
|
||||
* @radius: the blur radius
|
||||
*
|
||||
@@ -4076,9 +4076,9 @@ gsk_debug_node_diff (GskRenderNode *node1,
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_debug_node_new:
|
||||
* gsk_debug_node_new:
|
||||
* @child: The child to add debug info for
|
||||
* @message: (transfer full): The debug message
|
||||
* @message: (transfer full): The debug message
|
||||
*
|
||||
* Creates a #GskRenderNode that will add debug information about
|
||||
* the given @child.
|
||||
|
||||
+2
-1
@@ -123,7 +123,8 @@ gsk_transform_alloc (const GskTransformClass *transform_class,
|
||||
|
||||
self->transform_class = transform_class;
|
||||
self->category = next ? MIN (category, next->category) : category;
|
||||
self->next = gsk_transform_is_identity (next) ? NULL : next;
|
||||
self->next = gsk_transform_is_identity (next) ? NULL : gsk_transform_ref (next);
|
||||
g_clear_pointer (&next, gsk_transform_unref);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -133,7 +133,6 @@
|
||||
#include <gtk/gtkfontchooserdialog.h>
|
||||
#include <gtk/gtkfontchooserwidget.h>
|
||||
#include <gtk/gtkframe.h>
|
||||
#include <gtk/gtkfunctionslistitemfactory.h>
|
||||
#include <gtk/gtkgesture.h>
|
||||
#include <gtk/gtkgestureclick.h>
|
||||
#include <gtk/gtkgesturedrag.h>
|
||||
@@ -214,6 +213,7 @@
|
||||
#include <gtk/gtkscrolledwindow.h>
|
||||
#include <gtk/gtksearchbar.h>
|
||||
#include <gtk/gtksearchentry.h>
|
||||
#include <gtk/gtkselectionfiltermodel.h>
|
||||
#include <gtk/gtkselectionmodel.h>
|
||||
#include <gtk/gtkseparator.h>
|
||||
#include <gtk/gtksettings.h>
|
||||
@@ -247,6 +247,7 @@
|
||||
#include <gtk/gtkstringsorter.h>
|
||||
#include <gtk/gtkstylecontext.h>
|
||||
#include <gtk/gtkstyleprovider.h>
|
||||
#include <gtk/gtksuggestionentry.h>
|
||||
#include <gtk/gtkswitch.h>
|
||||
#include <gtk/gtktext.h>
|
||||
#include <gtk/gtktextbuffer.h>
|
||||
|
||||
+6
-6
@@ -707,7 +707,7 @@ gtk_bitset_shift_right (GtkBitset *self,
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_bitset_slice:
|
||||
* gtk_bitset_splice:
|
||||
* @self: a #GtkBitset
|
||||
* @position: position at which to slice
|
||||
* @removed: number of values to remove
|
||||
@@ -725,10 +725,10 @@ gtk_bitset_shift_right (GtkBitset *self,
|
||||
* up space that can then be filled.
|
||||
**/
|
||||
void
|
||||
gtk_bitset_slice (GtkBitset *self,
|
||||
guint position,
|
||||
guint removed,
|
||||
guint added)
|
||||
gtk_bitset_splice (GtkBitset *self,
|
||||
guint position,
|
||||
guint removed,
|
||||
guint added)
|
||||
{
|
||||
g_return_if_fail (self != NULL);
|
||||
/* overflow */
|
||||
@@ -742,7 +742,7 @@ gtk_bitset_slice (GtkBitset *self,
|
||||
GtkBitset *shift = gtk_bitset_copy (self);
|
||||
|
||||
gtk_bitset_remove_range (shift, 0, position);
|
||||
gtk_bitset_remove_range (self, position, G_MAXUINT - position + 1);
|
||||
gtk_bitset_remove_range_closed (self, position, G_MAXUINT);
|
||||
if (added > removed)
|
||||
gtk_bitset_shift_right (shift, added - removed);
|
||||
else
|
||||
|
||||
+1
-1
@@ -125,7 +125,7 @@ GDK_AVAILABLE_IN_ALL
|
||||
void gtk_bitset_shift_right (GtkBitset *self,
|
||||
guint amount);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_bitset_slice (GtkBitset *self,
|
||||
void gtk_bitset_splice (GtkBitset *self,
|
||||
guint position,
|
||||
guint removed,
|
||||
guint added);
|
||||
|
||||
@@ -369,6 +369,8 @@ gtk_bookmark_list_start_loading (GtkBookmarkList *self)
|
||||
self);
|
||||
g_object_unref (file);
|
||||
}
|
||||
|
||||
g_strfreev (uris);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
/**
|
||||
* SECTION:gtkbuilderlistitemfactory
|
||||
* @Tiitle: GtkBuilderListItemFactory
|
||||
* @Title: GtkBuilderListItemFactory
|
||||
* @Short_description: A listitem factory using ui files
|
||||
*
|
||||
* #GtkBuilderListItemFactory is a #GtkListItemFactory that creates
|
||||
|
||||
+2
-2
@@ -940,7 +940,7 @@ header_drag_end (GtkGestureDrag *gesture,
|
||||
|
||||
column = g_list_model_get_item (G_LIST_MODEL (self->columns), self->drag_pos);
|
||||
header = gtk_column_view_column_get_header (column);
|
||||
gtk_style_context_remove_class (gtk_widget_get_style_context (header), "dnd");
|
||||
gtk_widget_remove_css_class (header, "dnd");
|
||||
|
||||
sequence = gtk_gesture_single_get_current_sequence (GTK_GESTURE_SINGLE (gesture));
|
||||
if (!gtk_gesture_handles_sequence (GTK_GESTURE (gesture), sequence))
|
||||
@@ -1027,7 +1027,7 @@ header_drag_update (GtkGestureDrag *gesture,
|
||||
header = gtk_column_view_column_get_header (column);
|
||||
|
||||
gtk_widget_insert_after (header, self->header, gtk_widget_get_last_child (self->header));
|
||||
gtk_style_context_add_class (gtk_widget_get_style_context (header), "dnd");
|
||||
gtk_widget_add_css_class (header, "dnd");
|
||||
|
||||
gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED);
|
||||
if (!gtk_widget_has_focus (GTK_WIDGET (self)))
|
||||
|
||||
+17
-18
@@ -562,10 +562,12 @@ css_provider_commit (GtkCssProvider *css_provider,
|
||||
|
||||
if (ruleset->styles == NULL)
|
||||
{
|
||||
for (i = 0; i < n_selectors; i++)
|
||||
_gtk_css_selector_free (selectors[i]);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < n_selectors; i ++)
|
||||
for (i = 0; i < n_selectors; i++)
|
||||
{
|
||||
GtkCssRuleset *new;
|
||||
|
||||
@@ -768,7 +770,11 @@ parse_selector_list (GtkCssScanner *scanner,
|
||||
GtkCssSelector *select = _gtk_css_selector_parse (scanner->parser);
|
||||
|
||||
if (select == NULL)
|
||||
return 0;
|
||||
{
|
||||
for (int i = 0; i < n_selectors; i++)
|
||||
g_clear_pointer (&out_selectors[i], _gtk_css_selector_free);
|
||||
return 0;
|
||||
}
|
||||
|
||||
out_selectors[n_selectors] = select;
|
||||
n_selectors++;
|
||||
@@ -778,6 +784,8 @@ parse_selector_list (GtkCssScanner *scanner,
|
||||
gtk_css_parser_error_syntax (scanner->parser,
|
||||
"Only %u selectors per ruleset allowed",
|
||||
MAX_SELECTOR_LIST_LENGTH);
|
||||
for (int i = 0; i < MAX_SELECTOR_LIST_LENGTH; i++)
|
||||
g_clear_pointer (&out_selectors[i], _gtk_css_selector_free);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -806,10 +814,7 @@ parse_declaration (GtkCssScanner *scanner,
|
||||
|
||||
name = gtk_css_parser_consume_ident (scanner->parser);
|
||||
if (name == NULL)
|
||||
{
|
||||
gtk_css_parser_end_block (scanner->parser);
|
||||
return;
|
||||
}
|
||||
goto out;
|
||||
|
||||
property = _gtk_style_property_lookup (name);
|
||||
|
||||
@@ -821,25 +826,18 @@ parse_declaration (GtkCssScanner *scanner,
|
||||
if (!gtk_css_parser_try_token (scanner->parser, GTK_CSS_TOKEN_COLON))
|
||||
{
|
||||
gtk_css_parser_error_syntax (scanner->parser, "Expected ':'");
|
||||
g_free (name);
|
||||
gtk_css_parser_end_block (scanner->parser);
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
|
||||
value = _gtk_style_property_parse_value (property,
|
||||
scanner->parser);
|
||||
value = _gtk_style_property_parse_value (property, scanner->parser);
|
||||
|
||||
if (value == NULL)
|
||||
{
|
||||
gtk_css_parser_end_block (scanner->parser);
|
||||
return;
|
||||
}
|
||||
goto out;
|
||||
|
||||
if (!gtk_css_parser_has_token (scanner->parser, GTK_CSS_TOKEN_EOF))
|
||||
{
|
||||
gtk_css_parser_error_syntax (scanner->parser, "Junk at end of value for %s", property->name);
|
||||
gtk_css_parser_end_block (scanner->parser);
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (gtk_keep_css_sections)
|
||||
@@ -884,6 +882,7 @@ parse_declaration (GtkCssScanner *scanner,
|
||||
gtk_css_parser_error_value (scanner->parser, "No property named \"%s\"", name);
|
||||
}
|
||||
|
||||
out:
|
||||
g_free (name);
|
||||
|
||||
gtk_css_parser_end_block (scanner->parser);
|
||||
@@ -918,7 +917,7 @@ parse_ruleset (GtkCssScanner *scanner)
|
||||
{
|
||||
guint i;
|
||||
gtk_css_parser_error_syntax (scanner->parser, "Expected '{' after selectors");
|
||||
for (i = 0; i < n_selectors; i ++)
|
||||
for (i = 0; i < n_selectors; i++)
|
||||
_gtk_css_selector_free (selectors[i]);
|
||||
gtk_css_parser_skip_until (scanner->parser, GTK_CSS_TOKEN_OPEN_CURLY);
|
||||
gtk_css_parser_skip (scanner->parser);
|
||||
|
||||
@@ -321,7 +321,7 @@ gtk_custom_paper_unix_dialog_init (GtkCustomPaperUnixDialog *dialog)
|
||||
g_list_store_append (printer_list_list, printer_list);
|
||||
g_object_unref (printer_list);
|
||||
|
||||
full_list = G_LIST_MODEL (gtk_flatten_list_model_new (GTK_TYPE_PRINTER, G_LIST_MODEL (printer_list_list)));
|
||||
full_list = G_LIST_MODEL (gtk_flatten_list_model_new (G_LIST_MODEL (printer_list_list)));
|
||||
g_object_unref (printer_list_list);
|
||||
|
||||
filter = gtk_custom_filter_new (match_func, NULL, NULL);
|
||||
|
||||
+229
-4
@@ -62,6 +62,7 @@ enum {
|
||||
PROP_IO_PRIORITY,
|
||||
PROP_ITEM_TYPE,
|
||||
PROP_LOADING,
|
||||
PROP_MONITORED,
|
||||
NUM_PROPERTIES
|
||||
};
|
||||
|
||||
@@ -70,8 +71,10 @@ struct _GtkDirectoryList
|
||||
GObject parent_instance;
|
||||
|
||||
char *attributes;
|
||||
int io_priority;
|
||||
GFile *file;
|
||||
GFileMonitor *monitor;
|
||||
gboolean monitored;
|
||||
int io_priority;
|
||||
|
||||
GCancellable *cancellable;
|
||||
GError *error; /* Error while loading */
|
||||
@@ -147,13 +150,17 @@ gtk_directory_list_set_property (GObject *object,
|
||||
gtk_directory_list_set_io_priority (self, g_value_get_int (value));
|
||||
break;
|
||||
|
||||
case PROP_MONITORED:
|
||||
gtk_directory_list_set_monitored (self, g_value_get_boolean (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
static void
|
||||
gtk_directory_list_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
@@ -187,6 +194,10 @@ gtk_directory_list_get_property (GObject *object,
|
||||
g_value_set_boolean (value, gtk_directory_list_is_loading (self));
|
||||
break;
|
||||
|
||||
case PROP_MONITORED:
|
||||
g_value_set_boolean (value, gtk_directory_list_get_monitored (self));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@@ -204,12 +215,27 @@ gtk_directory_list_stop_loading (GtkDirectoryList *self)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void directory_changed (GFileMonitor *monitor,
|
||||
GFile *file,
|
||||
GFile *other_file,
|
||||
GFileMonitorEvent event,
|
||||
gpointer data);
|
||||
|
||||
static void
|
||||
gtk_directory_list_stop_monitoring (GtkDirectoryList *self)
|
||||
{
|
||||
if (self->monitor)
|
||||
g_signal_handlers_disconnect_by_func (self->monitor, directory_changed, self);
|
||||
g_clear_object (&self->monitor);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_directory_list_dispose (GObject *object)
|
||||
{
|
||||
GtkDirectoryList *self = GTK_DIRECTORY_LIST (object);
|
||||
|
||||
gtk_directory_list_stop_loading (self);
|
||||
gtk_directory_list_stop_monitoring (self);
|
||||
|
||||
g_clear_object (&self->file);
|
||||
g_clear_pointer (&self->attributes, g_free);
|
||||
@@ -301,6 +327,18 @@ gtk_directory_list_class_init (GtkDirectoryListClass *class)
|
||||
FALSE,
|
||||
GTK_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GtkDirectoryList:monitored:
|
||||
*
|
||||
* %TRUE if the directory is monitored for changed
|
||||
*/
|
||||
properties[PROP_MONITORED] =
|
||||
g_param_spec_boolean ("monitored",
|
||||
P_("monitored"),
|
||||
P_("TRUE if the directory is monitored for changes"),
|
||||
TRUE,
|
||||
GTK_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
g_object_class_install_properties (gobject_class, NUM_PROPERTIES, properties);
|
||||
}
|
||||
|
||||
@@ -309,6 +347,7 @@ gtk_directory_list_init (GtkDirectoryList *self)
|
||||
{
|
||||
self->items = g_sequence_new (g_object_unref);
|
||||
self->io_priority = G_PRIORITY_DEFAULT;
|
||||
self->monitored = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -324,7 +363,6 @@ gtk_directory_list_init (GtkDirectoryList *self)
|
||||
GtkDirectoryList *
|
||||
gtk_directory_list_new (const char *attributes,
|
||||
GFile *file)
|
||||
|
||||
{
|
||||
g_return_val_if_fail (file == NULL || G_IS_FILE (file), NULL);
|
||||
|
||||
@@ -410,7 +448,7 @@ gtk_directory_list_got_files_cb (GObject *source,
|
||||
{
|
||||
GFileInfo *info;
|
||||
GFile *file;
|
||||
|
||||
|
||||
info = l->data;
|
||||
file = g_file_enumerator_get_child (enumerator, info);
|
||||
g_file_info_set_attribute_object (info, "standard::file", G_OBJECT (file));
|
||||
@@ -496,6 +534,143 @@ gtk_directory_list_start_loading (GtkDirectoryList *self)
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_LOADING]);
|
||||
}
|
||||
|
||||
static void
|
||||
got_new_file_info_cb (GObject *source,
|
||||
GAsyncResult *res,
|
||||
gpointer data)
|
||||
{
|
||||
GFile *file = G_FILE (source);
|
||||
GtkDirectoryList *self = GTK_DIRECTORY_LIST (data);
|
||||
GFileInfo *info;
|
||||
guint position;
|
||||
|
||||
info = g_file_query_info_finish (file, res, NULL);
|
||||
if (!info)
|
||||
return;
|
||||
|
||||
g_file_info_set_attribute_object (info, "standard::file", G_OBJECT (file));
|
||||
position = g_sequence_get_length (self->items);
|
||||
g_sequence_append (self->items, info);
|
||||
g_list_model_items_changed (G_LIST_MODEL (self), position, 0, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
got_existing_file_info_cb (GObject *source,
|
||||
GAsyncResult *res,
|
||||
gpointer data)
|
||||
{
|
||||
GFile *file = G_FILE (source);
|
||||
GtkDirectoryList *self = GTK_DIRECTORY_LIST (data);
|
||||
GFileInfo *info;
|
||||
GSequenceIter *iter;
|
||||
|
||||
info = g_file_query_info_finish (file, res, NULL);
|
||||
if (!info)
|
||||
return;
|
||||
|
||||
g_file_info_set_attribute_object (info, "standard::file", G_OBJECT (file));
|
||||
|
||||
for (iter = g_sequence_get_begin_iter (self->items);
|
||||
!g_sequence_iter_is_end (iter);
|
||||
iter = g_sequence_iter_next (iter))
|
||||
{
|
||||
GFileInfo *item = g_sequence_get (iter);
|
||||
GFile *f = G_FILE (g_file_info_get_attribute_object (item, "standard::file"));
|
||||
if (g_file_equal (f, file))
|
||||
{
|
||||
guint position = g_sequence_iter_get_position (iter);
|
||||
g_sequence_set (iter, g_object_ref (info));
|
||||
g_list_model_items_changed (G_LIST_MODEL (self), position, 1, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_directory_list_remove_file (GtkDirectoryList *self,
|
||||
GFile *file)
|
||||
{
|
||||
GSequenceIter *iter;
|
||||
|
||||
for (iter = g_sequence_get_begin_iter (self->items);
|
||||
!g_sequence_iter_is_end (iter);
|
||||
iter = g_sequence_iter_next (iter))
|
||||
{
|
||||
GFileInfo *item = g_sequence_get (iter);
|
||||
GFile *f = G_FILE (g_file_info_get_attribute_object (item, "standard::file"));
|
||||
if (g_file_equal (f, file))
|
||||
{
|
||||
guint position = g_sequence_iter_get_position (iter);
|
||||
g_sequence_remove (iter);
|
||||
g_list_model_items_changed (G_LIST_MODEL (self), position, 1, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
directory_changed (GFileMonitor *monitor,
|
||||
GFile *file,
|
||||
GFile *other_file,
|
||||
GFileMonitorEvent event,
|
||||
gpointer data)
|
||||
{
|
||||
GtkDirectoryList *self = GTK_DIRECTORY_LIST (data);
|
||||
switch (event)
|
||||
{
|
||||
case G_FILE_MONITOR_EVENT_CREATED:
|
||||
g_file_query_info_async (file,
|
||||
self->attributes,
|
||||
G_FILE_QUERY_INFO_NONE,
|
||||
self->io_priority,
|
||||
self->cancellable,
|
||||
got_new_file_info_cb,
|
||||
self);
|
||||
break;
|
||||
|
||||
case G_FILE_MONITOR_EVENT_DELETED:
|
||||
gtk_directory_list_remove_file (self, file);
|
||||
break;
|
||||
|
||||
case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED:
|
||||
g_file_query_info_async (file,
|
||||
self->attributes,
|
||||
G_FILE_QUERY_INFO_NONE,
|
||||
self->io_priority,
|
||||
self->cancellable,
|
||||
got_existing_file_info_cb,
|
||||
self);
|
||||
break;
|
||||
|
||||
case G_FILE_MONITOR_EVENT_CHANGED:
|
||||
case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
|
||||
case G_FILE_MONITOR_EVENT_PRE_UNMOUNT:
|
||||
case G_FILE_MONITOR_EVENT_UNMOUNTED:
|
||||
case G_FILE_MONITOR_EVENT_MOVED:
|
||||
case G_FILE_MONITOR_EVENT_RENAMED:
|
||||
case G_FILE_MONITOR_EVENT_MOVED_IN:
|
||||
case G_FILE_MONITOR_EVENT_MOVED_OUT:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_directory_list_start_monitoring (GtkDirectoryList *self)
|
||||
{
|
||||
g_assert (self->monitor == NULL);
|
||||
self->monitor = g_file_monitor_directory (self->file, G_FILE_MONITOR_NONE, NULL, NULL);
|
||||
g_signal_connect (self->monitor, "changed", G_CALLBACK (directory_changed), self);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_directory_list_update_monitoring (GtkDirectoryList *self)
|
||||
{
|
||||
gtk_directory_list_stop_monitoring (self);
|
||||
if (self->file && self->monitored)
|
||||
gtk_directory_list_start_monitoring (self);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_directory_list_set_file:
|
||||
* @self: a #GtkDirectoryList
|
||||
@@ -520,6 +695,7 @@ gtk_directory_list_set_file (GtkDirectoryList *self,
|
||||
|
||||
g_set_object (&self->file, file);
|
||||
|
||||
gtk_directory_list_update_monitoring (self);
|
||||
gtk_directory_list_start_loading (self);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FILE]);
|
||||
@@ -679,3 +855,52 @@ gtk_directory_list_get_error (GtkDirectoryList *self)
|
||||
return self->error;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_directory_list_set_monitored:
|
||||
* @self: a #GtkDirectoryList
|
||||
* @monitored: %TRUE to monitor the directory for changes
|
||||
*
|
||||
* Sets whether the directory list will monitor the directory
|
||||
* for changes. If monitoring is enabled, the
|
||||
* #GListModel::items-changed signal will be emitted when the
|
||||
* directory contents change.
|
||||
*
|
||||
* When monitoring is turned on after the initial creation
|
||||
* of the directory list, the directory is reloaded to avoid
|
||||
* missing files that appeared between the initial loading
|
||||
* and when monitoring was turned on.
|
||||
*/
|
||||
void
|
||||
gtk_directory_list_set_monitored (GtkDirectoryList *self,
|
||||
gboolean monitored)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_DIRECTORY_LIST (self));
|
||||
|
||||
if (self->monitored == monitored)
|
||||
return;
|
||||
|
||||
self->monitored = monitored;
|
||||
|
||||
gtk_directory_list_update_monitoring (self);
|
||||
if (monitored)
|
||||
gtk_directory_list_start_loading (self);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_MONITORED]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_directory_list_get_monitored:
|
||||
* @self: a #GtkDirectoryList
|
||||
*
|
||||
* Returns whether the directory list is monitoring
|
||||
* the directory for changes.
|
||||
*
|
||||
* Returns: %TRUE if the directory is monitored
|
||||
*/
|
||||
gboolean
|
||||
gtk_directory_list_get_monitored (GtkDirectoryList *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_DIRECTORY_LIST (self), TRUE);
|
||||
|
||||
return self->monitored;
|
||||
}
|
||||
|
||||
@@ -62,6 +62,12 @@ gboolean gtk_directory_list_is_loading (GtkDirectoryLis
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
const GError * gtk_directory_list_get_error (GtkDirectoryList *self);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_directory_list_set_monitored (GtkDirectoryList *self,
|
||||
gboolean monitored);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_directory_list_get_monitored (GtkDirectoryList *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_DIRECTORY_LIST_H__ */
|
||||
|
||||
@@ -224,7 +224,7 @@ gtk_drop_controller_motion_class_init (GtkDropControllerMotionClass *klass)
|
||||
props[PROP_CONTAINS_POINTER] =
|
||||
g_param_spec_boolean ("contains-pointer",
|
||||
P_("Contains Pointer"),
|
||||
P_("Whether the pointer is inthe controllers widget or a descendant"),
|
||||
P_("Whether the pointer is in the controllers widget or a descendant"),
|
||||
FALSE,
|
||||
G_PARAM_READABLE);
|
||||
|
||||
|
||||
+1
-1
@@ -927,7 +927,7 @@ gtk_drop_down_get_expression (GtkDropDown *self)
|
||||
/**
|
||||
* gtk_drop_down_set_from_strings:
|
||||
* @self: a #GtkDropDown
|
||||
* @texts: a %NULL-terminated string array
|
||||
* @texts: (array zero-terminated=1) (element-type utf8): a %NULL-terminated string array
|
||||
*
|
||||
* Populates @self with the strings in @text,
|
||||
* by creating a suitable model and factory.
|
||||
|
||||
@@ -221,7 +221,7 @@ gtk_event_controller_motion_class_init (GtkEventControllerMotionClass *klass)
|
||||
props[PROP_CONTAINS_POINTER] =
|
||||
g_param_spec_boolean ("contains-pointer",
|
||||
P_("Contains Pointer"),
|
||||
P_("Whether the pointer is inthe controllers widget or a descendant"),
|
||||
P_("Whether the pointer is in the controllers widget or a descendant"),
|
||||
FALSE,
|
||||
G_PARAM_READABLE);
|
||||
|
||||
|
||||
+44
-11
@@ -1,3 +1,4 @@
|
||||
|
||||
/*
|
||||
* Copyright © 2019 Benjamin Otte
|
||||
*
|
||||
@@ -28,18 +29,50 @@
|
||||
* @Short_description: Expressions to values
|
||||
* @Title: GtkExpression
|
||||
*
|
||||
* GtkExpression provides a way to describe references to #GValues.
|
||||
* GtkExpression provides a way to describe references to values.
|
||||
*
|
||||
* An expression needs to be "evaluated" to obtain the value that it currently refers
|
||||
* to. An evaluation always happens in the context of a current object called `this`
|
||||
* (it mirrors the behavior of object-oriented languages), which may or may not
|
||||
* influence the result of the evaluation. Use gtk_expression_evaluate() for
|
||||
* evaluating an expression.
|
||||
* An important aspect of expressions is that the value can be obtained
|
||||
* from a source that is several steps away. For example, an expression
|
||||
* may describe ‘the value of property A of @object1, which is itself the
|
||||
* value of a property of @object2’. And @object1 may not even exist yet
|
||||
* at the time that the expression is created. This is contrast to GObject
|
||||
* property bindings, which can only create direct connections between
|
||||
* the properties of two objects that must both exist for the duration
|
||||
* of the binding.
|
||||
*
|
||||
* An expression needs to be "evaluated" to obtain the value that it currently
|
||||
* refers to. An evaluation always happens in the context of a current object
|
||||
* called `this` (it mirrors the behavior of object-oriented languages),
|
||||
* which may or may not influence the result of the evaluation. Use
|
||||
* gtk_expression_evaluate() for evaluating an expression.
|
||||
*
|
||||
* Various methods for defining expressions exist, from simple constants via
|
||||
* gtk_constant_expression_new() to looking up properties in a #GObject (even
|
||||
* recursively) via gtk_property_expression_new() or providing custom functions to
|
||||
* transform and combine expressions via gtk_closure_expression_new().
|
||||
* recursively) via gtk_property_expression_new() or providing custom functions
|
||||
* to transform and combine expressions via gtk_closure_expression_new().
|
||||
*
|
||||
* Here is an example of a complex expression:
|
||||
* |[
|
||||
* color_expr = gtk_property_expression_new (GTK_TYPE_LIST_ITEM,
|
||||
* NULL, "item");
|
||||
* expression = gtk_property_expression_new (GTK_TYPE_COLOR,
|
||||
* color_expr,
|
||||
* "name");
|
||||
* ]|
|
||||
* when evaluated with `this` being a GtkListItem, it will obtain the
|
||||
* "item" property from the GtkListItem, and then obtain the "name" property
|
||||
* from the resulting object (which is assumed to be of type GTK_TYPE_COLOR).
|
||||
*
|
||||
* A more concise way to describe this would be
|
||||
* |[
|
||||
* this->item->name
|
||||
* ]|
|
||||
*
|
||||
* The most likely place where you will encounter expressions is in the context
|
||||
* of list models and list widgets using them. For example, #GtkDropDown is
|
||||
* evaluating a GtkExpression to obtain strings from the items in its model
|
||||
* that it can then use to match against the contents of its search entry.
|
||||
* #GtkStringFilter is using a GtkExpression for a similar reason.
|
||||
*
|
||||
* By default, expressions are not paying attention to changes and evaluation is
|
||||
* just a snapshot of the current state at a given time. To get informed about
|
||||
@@ -1537,12 +1570,12 @@ GTK_DEFINE_EXPRESSION_TYPE (GtkCClosureExpression,
|
||||
/**
|
||||
* gtk_cclosure_expression_new:
|
||||
* @value_type: the type of the value that this expression evaluates to
|
||||
* @marshal: (scope call): marshaller used for creating a closure
|
||||
* @marshal: (scope call) (nullable): marshaller used for creating a closure
|
||||
* @n_params: the number of params needed for evaluating @closure
|
||||
* @params: (array length=n_params) (transfer full): expressions for each parameter
|
||||
* @callback_func: (scope notified) (closure user_data) (destroy user_destroy): callback used for creating a closure
|
||||
* @user_data: user data used for creating a closure
|
||||
* @user_destroy: destroy notify for @user_data
|
||||
* @user_data: (nullable): user data used for creating a closure
|
||||
* @user_destroy: (nullable): destroy notify for @user_data
|
||||
*
|
||||
* This function is a variant of gtk_closure_expression_new() that
|
||||
* creates a #GClosure by calling gtk_cclosure_new() with the given
|
||||
|
||||
+63
-102
@@ -79,75 +79,6 @@ G_DEFINE_INTERFACE (GtkFileChooser, gtk_file_chooser, G_TYPE_OBJECT);
|
||||
static void
|
||||
gtk_file_chooser_default_init (GtkFileChooserInterface *iface)
|
||||
{
|
||||
GType iface_type = G_TYPE_FROM_INTERFACE (iface);
|
||||
|
||||
/**
|
||||
* GtkFileChooser::current-folder-changed:
|
||||
* @chooser: the object which received the signal.
|
||||
*
|
||||
* This signal is emitted when the current folder in a #GtkFileChooser
|
||||
* changes. This can happen due to the user performing some action that
|
||||
* changes folders, such as selecting a bookmark or visiting a folder on the
|
||||
* file list. It can also happen as a result of calling a function to
|
||||
* explicitly change the current folder in a file chooser.
|
||||
*
|
||||
* Normally you do not need to connect to this signal, unless you need to keep
|
||||
* track of which folder a file chooser is showing.
|
||||
*
|
||||
* See also: gtk_file_chooser_set_current_folder(),
|
||||
* gtk_file_chooser_get_current_folder(),
|
||||
*/
|
||||
g_signal_new (I_("current-folder-changed"),
|
||||
iface_type,
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GtkFileChooserIface, current_folder_changed),
|
||||
NULL, NULL,
|
||||
NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
/**
|
||||
* GtkFileChooser::selection-changed:
|
||||
* @chooser: the object which received the signal.
|
||||
*
|
||||
* This signal is emitted when there is a change in the set of selected files
|
||||
* in a #GtkFileChooser. This can happen when the user modifies the selection
|
||||
* with the mouse or the keyboard, or when explicitly calling functions to
|
||||
* change the selection.
|
||||
*
|
||||
* Normally you do not need to connect to this signal, as it is easier to wait
|
||||
* for the file chooser to finish running, and then to get the list of
|
||||
* selected files using the functions mentioned below.
|
||||
*/
|
||||
g_signal_new (I_("selection-changed"),
|
||||
iface_type,
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GtkFileChooserIface, selection_changed),
|
||||
NULL, NULL,
|
||||
NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
/**
|
||||
* GtkFileChooser::file-activated:
|
||||
* @chooser: the object which received the signal.
|
||||
*
|
||||
* This signal is emitted when the user "activates" a file in the file
|
||||
* chooser. This can happen by double-clicking on a file in the file list, or
|
||||
* by pressing `Enter`.
|
||||
*
|
||||
* Normally you do not need to connect to this signal. It is used internally
|
||||
* by #GtkFileChooserDialog to know when to activate the default button in the
|
||||
* dialog.
|
||||
*
|
||||
* See also: gtk_file_chooser_get_file(), gtk_file_chooser_get_files()
|
||||
*/
|
||||
g_signal_new (I_("file-activated"),
|
||||
iface_type,
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GtkFileChooserIface, file_activated),
|
||||
NULL, NULL,
|
||||
NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
g_object_interface_install_property (iface,
|
||||
g_param_spec_enum ("action",
|
||||
P_("Action"),
|
||||
@@ -168,6 +99,38 @@ gtk_file_chooser_default_init (GtkFileChooserInterface *iface)
|
||||
FALSE,
|
||||
GTK_PARAM_READWRITE));
|
||||
|
||||
/**
|
||||
* GtkFileChooser:filters:
|
||||
*
|
||||
* A #GListModel containing the filters that have been
|
||||
* added with gtk_file_chooser_add_filter().
|
||||
*
|
||||
* The returned object should not be modified. It may
|
||||
* or may not be updated for later changes.
|
||||
*/
|
||||
g_object_interface_install_property (iface,
|
||||
g_param_spec_object ("filters",
|
||||
P_("Filters"),
|
||||
P_("List model of filters"),
|
||||
G_TYPE_LIST_MODEL,
|
||||
GTK_PARAM_READABLE));
|
||||
|
||||
/**
|
||||
* GtkFileChooser:shortcut-folders:
|
||||
*
|
||||
* A #GListModel containing the shortcut folders that have been
|
||||
* added with gtk_file_chooser_add_shortcut().
|
||||
*
|
||||
* The returned object should not be modified. It may
|
||||
* or may not be updated for later changes.
|
||||
*/
|
||||
g_object_interface_install_property (iface,
|
||||
g_param_spec_object ("shortcut-folders",
|
||||
P_("Shortcut Folders"),
|
||||
P_("List model of shortcut folders"),
|
||||
G_TYPE_LIST_MODEL,
|
||||
GTK_PARAM_READABLE));
|
||||
|
||||
/**
|
||||
* GtkFileChooser:create-folders:
|
||||
*
|
||||
@@ -476,16 +439,15 @@ gtk_file_chooser_unselect_file (GtkFileChooser *chooser,
|
||||
/**
|
||||
* gtk_file_chooser_get_files:
|
||||
* @chooser: a #GtkFileChooser
|
||||
*
|
||||
* Lists all the selected files and subfolders in the current folder of @chooser
|
||||
* as #GFile.
|
||||
*
|
||||
* Returns: (element-type GFile) (transfer full): a list
|
||||
* containing a #GFile for each selected file and subfolder in the
|
||||
* current folder. Free the returned list with g_slist_free(), and
|
||||
* the files with g_object_unref().
|
||||
**/
|
||||
GSList *
|
||||
* Lists all the selected files and subfolders in the current folder
|
||||
* of @chooser as #GFile.
|
||||
*
|
||||
* Returns: (transfer full): a list model containing a #GFile for each
|
||||
* selected file and subfolder in the current folder. Free the returned
|
||||
* list with g_object_unref().
|
||||
*/
|
||||
GListModel *
|
||||
gtk_file_chooser_get_files (GtkFileChooser *chooser)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), NULL);
|
||||
@@ -565,19 +527,15 @@ gtk_file_chooser_set_file (GtkFileChooser *chooser,
|
||||
GFile *
|
||||
gtk_file_chooser_get_file (GtkFileChooser *chooser)
|
||||
{
|
||||
GSList *list;
|
||||
GListModel *list;
|
||||
GFile *result = NULL;
|
||||
|
||||
|
||||
g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), NULL);
|
||||
|
||||
list = gtk_file_chooser_get_files (chooser);
|
||||
if (list)
|
||||
{
|
||||
result = list->data;
|
||||
list = g_slist_delete_link (list, list);
|
||||
|
||||
g_slist_free_full (list, g_object_unref);
|
||||
}
|
||||
if (g_list_model_get_n_items (list) > 0)
|
||||
result = g_list_model_get_item (list, 0);
|
||||
g_object_unref (list);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -682,23 +640,24 @@ gtk_file_chooser_remove_filter (GtkFileChooser *chooser,
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_file_chooser_list_filters:
|
||||
* gtk_file_chooser_get_filters:
|
||||
* @chooser: a #GtkFileChooser
|
||||
*
|
||||
* Lists the current set of user-selectable filters; see
|
||||
* Gets the current set of user-selectable filters, as a list model; see
|
||||
* gtk_file_chooser_add_filter(), gtk_file_chooser_remove_filter().
|
||||
*
|
||||
* Returns: (element-type GtkFileFilter) (transfer container): a
|
||||
* #GSList containing the current set of user selectable filters. The
|
||||
* contents of the list are owned by GTK+, but you must free the list
|
||||
* itself with g_slist_free() when you are done with it.
|
||||
* You should not modify the returned list model. Future changes to
|
||||
* @chooser may or may not affect the returned model.
|
||||
*
|
||||
* Returns: (transfer full): a #GListModel containing the current set
|
||||
* of user-selectable filters.
|
||||
**/
|
||||
GSList *
|
||||
gtk_file_chooser_list_filters (GtkFileChooser *chooser)
|
||||
GListModel *
|
||||
gtk_file_chooser_get_filters (GtkFileChooser *chooser)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), NULL);
|
||||
|
||||
return GTK_FILE_CHOOSER_GET_IFACE (chooser)->list_filters (chooser);
|
||||
return GTK_FILE_CHOOSER_GET_IFACE (chooser)->get_filters (chooser);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -750,21 +709,23 @@ gtk_file_chooser_get_filter (GtkFileChooser *chooser)
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_file_chooser_list_shortcut_folders:
|
||||
* gtk_file_chooser_get_shortcut_folders:
|
||||
* @chooser: a #GtkFileChooser
|
||||
*
|
||||
* Queries the list of shortcut folders in the file chooser, as set by
|
||||
* gtk_file_chooser_add_shortcut_folder().
|
||||
*
|
||||
* Returns: (nullable) (element-type Gio.File) (transfer full): A list
|
||||
* of folder filenames, or %NULL if there are no shortcut folders.
|
||||
* You should not modify the returned list model. Future changes to
|
||||
* @chooser may or may not affect the returned model.
|
||||
*
|
||||
* Returns: (transfer full): A list model of #GFiles
|
||||
*/
|
||||
GSList *
|
||||
gtk_file_chooser_list_shortcut_folders (GtkFileChooser *chooser)
|
||||
GListModel *
|
||||
gtk_file_chooser_get_shortcut_folders (GtkFileChooser *chooser)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), NULL);
|
||||
|
||||
return GTK_FILE_CHOOSER_GET_IFACE (chooser)->list_shortcut_folders (chooser);
|
||||
return GTK_FILE_CHOOSER_GET_IFACE (chooser)->get_shortcut_folders (chooser);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+61
-68
@@ -72,7 +72,8 @@ GType gtk_file_chooser_get_type (void) G_GNUC_CONST;
|
||||
* @GTK_FILE_CHOOSER_ERROR_BAD_FILENAME: Indicates a malformed filename.
|
||||
* @GTK_FILE_CHOOSER_ERROR_ALREADY_EXISTS: Indicates a duplicate path (e.g. when
|
||||
* adding a bookmark).
|
||||
* @GTK_FILE_CHOOSER_ERROR_INCOMPLETE_HOSTNAME: Indicates an incomplete hostname (e.g. "http://foo" without a slash after that).
|
||||
* @GTK_FILE_CHOOSER_ERROR_INCOMPLETE_HOSTNAME: Indicates an incomplete hostname
|
||||
* (e.g. "http://foo" without a slash after that).
|
||||
*
|
||||
* These identify the various errors that can occur while calling
|
||||
* #GtkFileChooser functions.
|
||||
@@ -87,108 +88,100 @@ typedef enum {
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GQuark gtk_file_chooser_error_quark (void);
|
||||
|
||||
/* Configuration
|
||||
*/
|
||||
/* Configuration */
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_file_chooser_set_action (GtkFileChooser *chooser,
|
||||
GtkFileChooserAction action);
|
||||
GtkFileChooserAction action);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkFileChooserAction gtk_file_chooser_get_action (GtkFileChooser *chooser);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_file_chooser_set_select_multiple (GtkFileChooser *chooser,
|
||||
gboolean select_multiple);
|
||||
gboolean select_multiple);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_file_chooser_get_select_multiple (GtkFileChooser *chooser);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_file_chooser_set_create_folders (GtkFileChooser *chooser,
|
||||
gboolean create_folders);
|
||||
gboolean create_folders);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_file_chooser_get_create_folders (GtkFileChooser *chooser);
|
||||
gboolean gtk_file_chooser_get_create_folders (GtkFileChooser *chooser);
|
||||
|
||||
/* Suggested name for the Save-type actions
|
||||
*/
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_file_chooser_set_current_name (GtkFileChooser *chooser,
|
||||
const gchar *name);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gchar *gtk_file_chooser_get_current_name (GtkFileChooser *chooser);
|
||||
/* Suggested name for the Save-type actions */
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_file_chooser_select_all (GtkFileChooser *chooser);
|
||||
void gtk_file_chooser_set_current_name (GtkFileChooser *chooser,
|
||||
const char *name);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_file_chooser_unselect_all (GtkFileChooser *chooser);
|
||||
char * gtk_file_chooser_get_current_name (GtkFileChooser *chooser);
|
||||
|
||||
/* GFile manipulation */
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GFile * gtk_file_chooser_get_file (GtkFileChooser *chooser);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_file_chooser_set_file (GtkFileChooser *chooser,
|
||||
GFile *file,
|
||||
GError **error);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_file_chooser_select_file (GtkFileChooser *chooser,
|
||||
GFile *file,
|
||||
GError **error);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_file_chooser_unselect_file (GtkFileChooser *chooser,
|
||||
GFile *file);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GSList * gtk_file_chooser_get_files (GtkFileChooser *chooser);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_file_chooser_set_current_folder (GtkFileChooser *chooser,
|
||||
GFile *file,
|
||||
GError **error);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GFile * gtk_file_chooser_get_current_folder (GtkFileChooser *chooser);
|
||||
|
||||
/* List of user selectable filters
|
||||
*/
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_file_chooser_add_filter (GtkFileChooser *chooser,
|
||||
GtkFileFilter *filter);
|
||||
GFile * gtk_file_chooser_get_file (GtkFileChooser *chooser);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_file_chooser_remove_filter (GtkFileChooser *chooser,
|
||||
GtkFileFilter *filter);
|
||||
gboolean gtk_file_chooser_set_file (GtkFileChooser *chooser,
|
||||
GFile *file,
|
||||
GError **error);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GSList *gtk_file_chooser_list_filters (GtkFileChooser *chooser);
|
||||
GListModel * gtk_file_chooser_get_files (GtkFileChooser *chooser);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_file_chooser_set_current_folder (GtkFileChooser *chooser,
|
||||
GFile *file,
|
||||
GError **error);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GFile * gtk_file_chooser_get_current_folder (GtkFileChooser *chooser);
|
||||
|
||||
/* List of user selectable filters */
|
||||
|
||||
/* Current filter
|
||||
*/
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_file_chooser_set_filter (GtkFileChooser *chooser,
|
||||
GtkFileFilter *filter);
|
||||
void gtk_file_chooser_add_filter (GtkFileChooser *chooser,
|
||||
GtkFileFilter *filter);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkFileFilter *gtk_file_chooser_get_filter (GtkFileChooser *chooser);
|
||||
void gtk_file_chooser_remove_filter (GtkFileChooser *chooser,
|
||||
GtkFileFilter *filter);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GListModel * gtk_file_chooser_get_filters (GtkFileChooser *chooser);
|
||||
|
||||
/* Current filter */
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_file_chooser_set_filter (GtkFileChooser *chooser,
|
||||
GtkFileFilter *filter);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkFileFilter * gtk_file_chooser_get_filter (GtkFileChooser *chooser);
|
||||
|
||||
/* Per-application shortcut folders */
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_file_chooser_add_shortcut_folder (GtkFileChooser *chooser,
|
||||
GFile *folder,
|
||||
GError **error);
|
||||
gboolean gtk_file_chooser_add_shortcut_folder (GtkFileChooser *chooser,
|
||||
GFile *folder,
|
||||
GError **error);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_file_chooser_remove_shortcut_folder (GtkFileChooser *chooser,
|
||||
GFile *folder,
|
||||
GError **error);
|
||||
gboolean gtk_file_chooser_remove_shortcut_folder
|
||||
(GtkFileChooser *chooser,
|
||||
GFile *folder,
|
||||
GError **error);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GSList *gtk_file_chooser_list_shortcut_folders (GtkFileChooser *chooser);
|
||||
GListModel * gtk_file_chooser_get_shortcut_folders (GtkFileChooser *chooser);
|
||||
|
||||
/* Custom widgets */
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_file_chooser_add_choice (GtkFileChooser *chooser,
|
||||
const char *id,
|
||||
const char *label,
|
||||
const char **options,
|
||||
const char **option_labels);
|
||||
void gtk_file_chooser_add_choice (GtkFileChooser *chooser,
|
||||
const char *id,
|
||||
const char *label,
|
||||
const char **options,
|
||||
const char **option_labels);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_file_chooser_remove_choice (GtkFileChooser *chooser,
|
||||
const char *id);
|
||||
void gtk_file_chooser_remove_choice (GtkFileChooser *chooser,
|
||||
const char *id);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_file_chooser_set_choice (GtkFileChooser *chooser,
|
||||
const char *id,
|
||||
const char *option);
|
||||
void gtk_file_chooser_set_choice (GtkFileChooser *chooser,
|
||||
const char *id,
|
||||
const char *option);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
const char *gtk_file_chooser_get_choice (GtkFileChooser *chooser,
|
||||
const char *id);
|
||||
const char * gtk_file_chooser_get_choice (GtkFileChooser *chooser,
|
||||
const char *id);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
+13
-11
@@ -244,7 +244,7 @@ static gboolean gtk_file_chooser_button_select_file (GtkFileChooser *chooser,
|
||||
static void gtk_file_chooser_button_unselect_file (GtkFileChooser *chooser,
|
||||
GFile *file);
|
||||
static void gtk_file_chooser_button_unselect_all (GtkFileChooser *chooser);
|
||||
static GSList *gtk_file_chooser_button_get_files (GtkFileChooser *chooser);
|
||||
static GListModel *gtk_file_chooser_button_get_files (GtkFileChooser *chooser);
|
||||
static gboolean gtk_file_chooser_button_add_shortcut_folder (GtkFileChooser *chooser,
|
||||
GFile *file,
|
||||
GError **error);
|
||||
@@ -627,7 +627,6 @@ emit_selection_changed_if_changing_selection (GtkFileChooserButton *button)
|
||||
if (button->is_changing_selection)
|
||||
{
|
||||
button->is_changing_selection = FALSE;
|
||||
g_signal_emit_by_name (button, "selection-changed");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -645,8 +644,6 @@ gtk_file_chooser_button_set_current_folder (GtkFileChooser *chooser,
|
||||
|
||||
update_combo_box (button);
|
||||
|
||||
g_signal_emit_by_name (button, "current-folder-changed");
|
||||
|
||||
if (button->active)
|
||||
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (button->chooser), file, NULL);
|
||||
|
||||
@@ -750,17 +747,23 @@ get_selected_file (GtkFileChooserButton *button)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static GSList *
|
||||
static GListModel *
|
||||
gtk_file_chooser_button_get_files (GtkFileChooser *chooser)
|
||||
{
|
||||
GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (chooser);
|
||||
GFile *file;
|
||||
GListStore *store;
|
||||
|
||||
store = g_list_store_new (G_TYPE_FILE);
|
||||
|
||||
file = get_selected_file (button);
|
||||
if (file)
|
||||
return g_slist_prepend (NULL, file);
|
||||
else
|
||||
return NULL;
|
||||
{
|
||||
g_list_store_append (store, file);
|
||||
g_object_unref (file);
|
||||
}
|
||||
|
||||
return G_LIST_MODEL (store);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -1035,6 +1038,8 @@ gtk_file_chooser_button_get_property (GObject *object,
|
||||
case GTK_FILE_CHOOSER_PROP_FILTER:
|
||||
case GTK_FILE_CHOOSER_PROP_SELECT_MULTIPLE:
|
||||
case GTK_FILE_CHOOSER_PROP_CREATE_FOLDERS:
|
||||
case GTK_FILE_CHOOSER_PROP_FILTERS:
|
||||
case GTK_FILE_CHOOSER_PROP_SHORTCUT_FOLDERS:
|
||||
g_object_get_property (G_OBJECT (button->chooser), pspec->name, value);
|
||||
break;
|
||||
|
||||
@@ -2510,9 +2515,6 @@ common_response_cb (GtkFileChooserButton *button,
|
||||
response == GTK_RESPONSE_OK)
|
||||
{
|
||||
save_inactive_state (button);
|
||||
|
||||
g_signal_emit_by_name (button, "current-folder-changed");
|
||||
g_signal_emit_by_name (button, "selection-changed");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -265,12 +265,8 @@ static void gtk_file_chooser_dialog_size_allocate (GtkWidget *wid
|
||||
int width,
|
||||
int height,
|
||||
int baseline);
|
||||
static void file_chooser_widget_file_activated (GtkFileChooser *chooser,
|
||||
GtkFileChooserDialog *dialog);
|
||||
static void file_chooser_widget_response_requested (GtkWidget *widget,
|
||||
GtkFileChooserDialog *dialog);
|
||||
static void file_chooser_widget_selection_changed (GtkWidget *widget,
|
||||
GtkFileChooserDialog *dialog);
|
||||
|
||||
static void response_cb (GtkDialog *dialog,
|
||||
gint response_id);
|
||||
@@ -310,9 +306,7 @@ gtk_file_chooser_dialog_class_init (GtkFileChooserDialogClass *class)
|
||||
gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserDialog, widget);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserDialog, buttons);
|
||||
gtk_widget_class_bind_template_callback (widget_class, response_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, file_chooser_widget_file_activated);
|
||||
gtk_widget_class_bind_template_callback (widget_class, file_chooser_widget_response_requested);
|
||||
gtk_widget_class_bind_template_callback (widget_class, file_chooser_widget_selection_changed);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -367,34 +361,6 @@ is_accept_response_id (gint response_id)
|
||||
response_id == GTK_RESPONSE_APPLY);
|
||||
}
|
||||
|
||||
/* Callback used when the user activates a file in the file chooser widget */
|
||||
static void
|
||||
file_chooser_widget_file_activated (GtkFileChooser *chooser,
|
||||
GtkFileChooserDialog *dialog)
|
||||
{
|
||||
gtk_widget_activate_default (GTK_WIDGET (chooser));
|
||||
}
|
||||
|
||||
static void
|
||||
file_chooser_widget_selection_changed (GtkWidget *widget,
|
||||
GtkFileChooserDialog *dialog)
|
||||
{
|
||||
GtkFileChooserDialogPrivate *priv = gtk_file_chooser_dialog_get_instance_private (dialog);
|
||||
GtkWidget *button;
|
||||
GSList *files;
|
||||
gboolean sensitive;
|
||||
|
||||
button = get_accept_action_widget (GTK_DIALOG (dialog), FALSE);
|
||||
if (button == NULL)
|
||||
return;
|
||||
|
||||
files = gtk_file_chooser_get_files (GTK_FILE_CHOOSER (priv->widget));
|
||||
sensitive = (files != NULL);
|
||||
gtk_widget_set_sensitive (button, sensitive);
|
||||
|
||||
g_slist_free_full (files, g_object_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
file_chooser_widget_response_requested (GtkWidget *widget,
|
||||
GtkFileChooserDialog *dialog)
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "gtkintl.h"
|
||||
#include "gtkmarshalers.h"
|
||||
#include "gtkfilefilterprivate.h"
|
||||
#include "gtkfilter.h"
|
||||
#include "gtkeventcontrollerfocus.h"
|
||||
|
||||
typedef struct _GtkFileChooserEntryClass GtkFileChooserEntryClass;
|
||||
@@ -194,65 +195,22 @@ match_func (GtkEntryCompletion *compl,
|
||||
* current file filter (e.g. just jpg files) here. */
|
||||
if (chooser_entry->current_filter != NULL)
|
||||
{
|
||||
char *mime_type = NULL;
|
||||
gboolean matches;
|
||||
GFile *file;
|
||||
GFileInfo *file_info;
|
||||
GtkFileFilterInfo filter_info;
|
||||
GtkFileFilterFlags needed_flags;
|
||||
GFileInfo *info;
|
||||
|
||||
file = _gtk_file_system_model_get_file (GTK_FILE_SYSTEM_MODEL (chooser_entry->completion_store),
|
||||
iter);
|
||||
file_info = _gtk_file_system_model_get_info (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);
|
||||
|
||||
/* We always allow navigating into subfolders, so don't ever filter directories */
|
||||
if (g_file_info_get_file_type (file_info) != G_FILE_TYPE_REGULAR)
|
||||
if (g_file_info_get_file_type (info) != G_FILE_TYPE_REGULAR)
|
||||
return TRUE;
|
||||
|
||||
needed_flags = gtk_file_filter_get_needed (chooser_entry->current_filter);
|
||||
if (!g_file_info_has_attribute (info, "standard::file"))
|
||||
g_file_info_set_attribute_object (info, "standard::file", G_OBJECT (file));
|
||||
|
||||
filter_info.display_name = g_file_info_get_display_name (file_info);
|
||||
filter_info.contains = GTK_FILE_FILTER_DISPLAY_NAME;
|
||||
|
||||
if (needed_flags & GTK_FILE_FILTER_MIME_TYPE)
|
||||
{
|
||||
const char *s = g_file_info_get_content_type (file_info);
|
||||
if (s != NULL)
|
||||
{
|
||||
mime_type = g_content_type_get_mime_type (s);
|
||||
if (mime_type != NULL)
|
||||
{
|
||||
filter_info.mime_type = mime_type;
|
||||
filter_info.contains |= GTK_FILE_FILTER_MIME_TYPE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (needed_flags & GTK_FILE_FILTER_FILENAME)
|
||||
{
|
||||
const char *path = g_file_get_path (file);
|
||||
if (path != NULL)
|
||||
{
|
||||
filter_info.filename = path;
|
||||
filter_info.contains |= GTK_FILE_FILTER_FILENAME;
|
||||
}
|
||||
}
|
||||
|
||||
if (needed_flags & GTK_FILE_FILTER_URI)
|
||||
{
|
||||
const char *uri = g_file_get_uri (file);
|
||||
if (uri)
|
||||
{
|
||||
filter_info.uri = uri;
|
||||
filter_info.contains |= GTK_FILE_FILTER_URI;
|
||||
}
|
||||
}
|
||||
|
||||
matches = gtk_file_filter_filter (chooser_entry->current_filter, &filter_info);
|
||||
|
||||
g_free (mime_type);
|
||||
return matches;
|
||||
return gtk_filter_match (GTK_FILTER (chooser_entry->current_filter), info);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
+15
-24
@@ -158,21 +158,8 @@
|
||||
* possible to use with #GtkFileChooserNative, as such use would
|
||||
* prohibit the use of a native dialog.
|
||||
*
|
||||
* There is no support for the signals that are emitted when the user
|
||||
* navigates in the dialog, including:
|
||||
* * #GtkFileChooser::current-folder-changed
|
||||
* * #GtkFileChooser::selection-changed
|
||||
* * #GtkFileChooser::file-activated
|
||||
*
|
||||
* You can also not use the methods that directly control user navigation:
|
||||
* * gtk_file_chooser_unselect_filename()
|
||||
* * gtk_file_chooser_select_all()
|
||||
* * gtk_file_chooser_unselect_all()
|
||||
*
|
||||
* If you need any of the above you will have to use #GtkFileChooserDialog directly.
|
||||
*
|
||||
* No operations that change the dialog work while the dialog is visible. Set
|
||||
* all the properties that are required before showing the dialog.
|
||||
* No operations that change the dialog work while the dialog is visible.
|
||||
* Set all the properties that are required before showing the dialog.
|
||||
*
|
||||
* ## Win32 details ## {#gtkfilechooserdialognative-win32}
|
||||
*
|
||||
@@ -180,7 +167,7 @@
|
||||
* used. It supports many of the features that #GtkFileChooserDialog
|
||||
* does, but there are some things it does not handle:
|
||||
*
|
||||
* * Any #GtkFileFilter added using a mimetype or custom filter.
|
||||
* * Any #GtkFileFilter added using a mimetype
|
||||
*
|
||||
* If any of these features are used the regular #GtkFileChooserDialog
|
||||
* will be used in place of the native one.
|
||||
@@ -190,10 +177,7 @@
|
||||
* When the org.freedesktop.portal.FileChooser portal is available on the
|
||||
* session bus, it is used to bring up an out-of-process file chooser. Depending
|
||||
* on the kind of session the application is running in, this may or may not
|
||||
* be a GTK+ file chooser. In this situation, the following things are not
|
||||
* supported and will be silently ignored:
|
||||
*
|
||||
* * Any #GtkFileFilter added with a custom filter.
|
||||
* be a GTK file chooser.
|
||||
*
|
||||
* ## macOS details ## {#gtkfilechooserdialognative-macos}
|
||||
*
|
||||
@@ -201,8 +185,6 @@
|
||||
* file chooser dialogs. Some features provided by #GtkFileChooserDialog are
|
||||
* not supported:
|
||||
*
|
||||
* * Any #GtkFileFilter added with a custom filter.
|
||||
*
|
||||
* * Shortcut folders.
|
||||
*/
|
||||
|
||||
@@ -683,7 +665,7 @@ gtk_file_chooser_native_set_current_name (GtkFileChooser *chooser,
|
||||
g_clear_object (&self->current_file);
|
||||
}
|
||||
|
||||
static GSList *
|
||||
static GListModel *
|
||||
gtk_file_chooser_native_get_files (GtkFileChooser *chooser)
|
||||
{
|
||||
GtkFileChooserNative *self = GTK_FILE_CHOOSER_NATIVE (chooser);
|
||||
@@ -693,7 +675,16 @@ gtk_file_chooser_native_get_files (GtkFileChooser *chooser)
|
||||
case MODE_PORTAL:
|
||||
case MODE_WIN32:
|
||||
case MODE_QUARTZ:
|
||||
return g_slist_copy_deep (self->custom_files, (GCopyFunc)g_object_ref, NULL);
|
||||
{
|
||||
GListStore *store;
|
||||
GSList *l;
|
||||
|
||||
store = g_list_store_new (G_TYPE_FILE);
|
||||
for (l = self->custom_files; l; l = l->next)
|
||||
g_list_store_append (store, l->data);
|
||||
|
||||
return G_LIST_MODEL (store);
|
||||
}
|
||||
|
||||
case MODE_FALLBACK:
|
||||
default:
|
||||
|
||||
@@ -126,7 +126,7 @@ response_cb (GDBusConnection *connection,
|
||||
if (current_filter)
|
||||
{
|
||||
GtkFileFilter *filter = gtk_file_filter_new_from_gvariant (current_filter);
|
||||
const gchar *current_filter_name = gtk_file_filter_get_name (filter);
|
||||
const char *current_filter_name = gtk_file_filter_get_name (filter);
|
||||
|
||||
/* Try to find the given filter in the list of filters.
|
||||
* Since filters are compared by pointer value, using the passed
|
||||
@@ -137,18 +137,24 @@ response_cb (GDBusConnection *connection,
|
||||
* If there is no match, just set the filter as it was retrieved.
|
||||
*/
|
||||
GtkFileFilter *filter_to_select = filter;
|
||||
GSList *filters = gtk_file_chooser_list_filters (GTK_FILE_CHOOSER (self));
|
||||
for (GSList *l = filters; l; l = l->next)
|
||||
GListModel *filters;
|
||||
guint j, n;
|
||||
|
||||
filters = gtk_file_chooser_get_filters (GTK_FILE_CHOOSER (self));
|
||||
n = g_list_model_get_n_items (filters);
|
||||
for (j = 0; j < n; j++)
|
||||
{
|
||||
GtkFileFilter *f = l->data;
|
||||
GtkFileFilter *f = g_list_model_get_item (filters, j);
|
||||
if (g_strcmp0 (gtk_file_filter_get_name (f), current_filter_name) == 0)
|
||||
{
|
||||
filter_to_select = f;
|
||||
break;
|
||||
}
|
||||
g_object_unref (f);
|
||||
}
|
||||
g_slist_free (filters);
|
||||
g_object_unref (filters);
|
||||
gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (self), filter_to_select);
|
||||
g_object_unref (filter_to_select);
|
||||
}
|
||||
|
||||
g_slist_free_full (self->custom_files, g_object_unref);
|
||||
@@ -264,17 +270,20 @@ open_file_msg_cb (GObject *source_object,
|
||||
static GVariant *
|
||||
get_filters (GtkFileChooser *self)
|
||||
{
|
||||
GSList *list, *l;
|
||||
GListModel *filters;
|
||||
guint n, i;
|
||||
GVariantBuilder builder;
|
||||
|
||||
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(sa(us))"));
|
||||
list = gtk_file_chooser_list_filters (self);
|
||||
for (l = list; l; l = l->next)
|
||||
filters = gtk_file_chooser_get_filters (self);
|
||||
n = g_list_model_get_n_items (filters);
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
GtkFileFilter *filter = l->data;
|
||||
GtkFileFilter *filter = g_list_model_get_item (filters, i);
|
||||
g_variant_builder_add (&builder, "@(sa(us))", gtk_file_filter_to_gvariant (filter));
|
||||
g_object_unref (filter);
|
||||
}
|
||||
g_slist_free (list);
|
||||
g_object_unref (filters);
|
||||
|
||||
return g_variant_builder_end (&builder);
|
||||
}
|
||||
|
||||
@@ -99,9 +99,10 @@ typedef struct {
|
||||
else
|
||||
[data->panel setAllowedFileTypes:filter];
|
||||
|
||||
GSList *filters = gtk_file_chooser_list_filters (GTK_FILE_CHOOSER (data->self));
|
||||
data->self->current_filter = g_slist_nth_data (filters, selected_index);
|
||||
g_slist_free (filters);
|
||||
GListModel *filters = gtk_file_chooser_get_filters (GTK_FILE_CHOOSER (data->self));
|
||||
data->self->current_filter = g_list_model_get_item (filters, selected_index);
|
||||
g_object_unref (data->self->current_filter);
|
||||
g_object_unref (filters);
|
||||
g_object_notify (G_OBJECT (data->self), "filter");
|
||||
}
|
||||
@end
|
||||
@@ -307,13 +308,28 @@ filechooser_quartz_launch (FileChooserQuartzData *data)
|
||||
|
||||
if (data->self->current_filter)
|
||||
{
|
||||
GSList *filters = gtk_file_chooser_list_filters (GTK_FILE_CHOOSER (data->self));
|
||||
gint current_filter_index = g_slist_index (filters, data->self->current_filter);
|
||||
g_slist_free (filters);
|
||||
GListModel *filters;
|
||||
guint i, n;
|
||||
guint current_filter_index = GTK_INVALID_LIST_POSITION;
|
||||
|
||||
if (current_filter_index >= 0)
|
||||
filters = gtk_file_chooser_get_filters (GTK_FILE_CHOOSER (data->self));
|
||||
n = g_list_model_get_n_items (filters);
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
gpointer item = g_list_model_get_item (filters, i);
|
||||
if (item == data->self->current_filter)
|
||||
{
|
||||
g_object_unref (item);
|
||||
current_filter_index = i;
|
||||
break;
|
||||
}
|
||||
g_object_unref (item);
|
||||
}
|
||||
g_object_unref (filters);
|
||||
|
||||
if (current_filter_index != GTK_INVALID_LIST_POSITION)
|
||||
[data->filter_combo_box selectItemAtIndex:current_filter_index];
|
||||
else
|
||||
else
|
||||
[data->filter_combo_box selectItemAtIndex:0];
|
||||
}
|
||||
else
|
||||
@@ -437,15 +453,15 @@ gtk_file_chooser_native_quartz_show (GtkFileChooserNative *self)
|
||||
GtkWindow *transient_for;
|
||||
GtkFileChooserAction action;
|
||||
|
||||
GSList *filters, *l;
|
||||
int n_filters, i;
|
||||
GListModel *filters;
|
||||
guint n_filters, i;
|
||||
char *message = NULL;
|
||||
|
||||
data = g_new0 (FileChooserQuartzData, 1);
|
||||
|
||||
// examine filters!
|
||||
filters = gtk_file_chooser_list_filters (GTK_FILE_CHOOSER (self));
|
||||
n_filters = g_slist_length (filters);
|
||||
filters = gtk_file_chooser_get_filters (GTK_FILE_CHOOSER (self));
|
||||
n_filters = g_list_model_get_n_items (filters);
|
||||
if (n_filters > 0)
|
||||
{
|
||||
data->filters = [NSMutableArray arrayWithCapacity:n_filters];
|
||||
@@ -453,13 +469,17 @@ gtk_file_chooser_native_quartz_show (GtkFileChooserNative *self)
|
||||
data->filter_names = [NSMutableArray arrayWithCapacity:n_filters];
|
||||
[data->filter_names retain];
|
||||
|
||||
for (l = filters, i = 0; l != NULL; l = l->next, i++)
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
if (!file_filter_to_quartz (l->data, data->filters, data->filter_names))
|
||||
GtkFileFilter *filter = g_list_model_get_item (filters, i);
|
||||
if (!file_filter_to_quartz (filter, data->filters, data->filter_names))
|
||||
{
|
||||
filechooser_quartz_data_free (data);
|
||||
g_object_unref (filter);
|
||||
g_object_unref (filters);
|
||||
return FALSE;
|
||||
}
|
||||
g_object_unref (filter);
|
||||
}
|
||||
self->current_filter = gtk_file_chooser_get_filter (GTK_FILE_CHOOSER (self));
|
||||
}
|
||||
@@ -467,6 +487,8 @@ gtk_file_chooser_native_quartz_show (GtkFileChooserNative *self)
|
||||
{
|
||||
self->current_filter = NULL;
|
||||
}
|
||||
g_object_unref (filters);
|
||||
|
||||
self->mode_data = data;
|
||||
data->self = g_object_ref (self);
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ typedef struct {
|
||||
char *cancel_label;
|
||||
char *title;
|
||||
|
||||
GSList *shortcut_files;
|
||||
GListModel *shortcut_files;
|
||||
GArray *choices_selections;
|
||||
|
||||
GFile *current_folder;
|
||||
@@ -244,9 +244,11 @@ ifiledialogevents_OnTypeChange (IFileDialogEvents * self,
|
||||
return S_OK;
|
||||
}
|
||||
fileType--; // fileTypeIndex starts at 1
|
||||
GSList *filters = gtk_file_chooser_list_filters (GTK_FILE_CHOOSER (events->data->self));
|
||||
events->data->self->current_filter = g_slist_nth_data (filters, fileType);
|
||||
g_slist_free (filters);
|
||||
GListModel *filters = gtk_file_chooser_get_filters (GTK_FILE_CHOOSER (events->data->self));
|
||||
GtkFileFilter *filter = g_list_model_get_item (filters, fileType);
|
||||
events->data->self->current_filter = filter;
|
||||
g_object_unref (filter);
|
||||
g_object_unref (filters);
|
||||
g_object_notify (G_OBJECT (events->data->self), "filter");
|
||||
return S_OK;
|
||||
}
|
||||
@@ -328,7 +330,7 @@ filechooser_win32_thread_data_free (FilechooserWin32ThreadData *data)
|
||||
g_array_free (data->choices_selections, TRUE);
|
||||
data->choices_selections = NULL;
|
||||
}
|
||||
g_slist_free_full (data->shortcut_files, g_object_unref);
|
||||
g_object_unref (data->shortcut_files);
|
||||
g_slist_free_full (data->files, g_object_unref);
|
||||
if (data->self)
|
||||
g_object_unref (data->self);
|
||||
@@ -463,7 +465,7 @@ filechooser_win32_thread (gpointer _data)
|
||||
IFileDialog2 *pfd2 = NULL;
|
||||
DWORD flags;
|
||||
DWORD cookie;
|
||||
GSList *l;
|
||||
guint j, n_items;
|
||||
|
||||
CoInitializeEx (NULL, COINIT_APARTMENTTHREADED);
|
||||
|
||||
@@ -529,9 +531,11 @@ filechooser_win32_thread (gpointer _data)
|
||||
g_free (label);
|
||||
}
|
||||
|
||||
for (l = data->shortcut_files; l != NULL; l = l->next)
|
||||
n_items = g_list_model_get_n_items (data->shortcut_files);
|
||||
for (j = 0; j < n_items; j++)
|
||||
{
|
||||
IShellItem *item = get_shell_item_for_file (l->data);
|
||||
GFile *file = g_list_model_get_item (data->shortcut_files, j);
|
||||
IShellItem *item = get_shell_item_for_file (file);
|
||||
if (item)
|
||||
{
|
||||
hr = IFileDialog_AddPlace (pfd, item, FDAP_BOTTOM);
|
||||
@@ -539,6 +543,7 @@ filechooser_win32_thread (gpointer _data)
|
||||
g_warning_hr ("Can't add dialog shortcut", hr);
|
||||
IShellItem_Release (item);
|
||||
}
|
||||
g_object_unref (file);
|
||||
}
|
||||
|
||||
if (data->current_file)
|
||||
@@ -591,9 +596,23 @@ filechooser_win32_thread (gpointer _data)
|
||||
|
||||
if (data->self->current_filter)
|
||||
{
|
||||
GSList *filters = gtk_file_chooser_list_filters (GTK_FILE_CHOOSER (data->self));
|
||||
gint current_filter_index = g_slist_index (filters, data->self->current_filter);
|
||||
g_slist_free (filters);
|
||||
GListModel *filters;
|
||||
guint current_filter_index = GTK_INVALID_LIST_POSITION;
|
||||
|
||||
filters = gtk_file_chooser_get_filters (GTK_FILE_CHOOSER (data->self));
|
||||
n_items = g_list_model_get_n_items (filters);
|
||||
for (j = 0; j < n_items; j++)
|
||||
{
|
||||
gpointer item = g_list_model_get_item (filters, j);
|
||||
if (item == data->self->current_filter)
|
||||
{
|
||||
current_filter_index = j;
|
||||
g_object_unref (item);
|
||||
break;
|
||||
}
|
||||
g_object_unref (item);
|
||||
}
|
||||
g_object_unref (filters);
|
||||
|
||||
if (current_filter_index >= 0)
|
||||
hr = IFileDialog_SetFileTypeIndex (pfd, current_filter_index + 1);
|
||||
@@ -617,6 +636,8 @@ filechooser_win32_thread (gpointer _data)
|
||||
hr = IFileDialog_QueryInterface (pfd, &IID_IFileDialogCustomize, (LPVOID *) &pfdc);
|
||||
if (SUCCEEDED (hr))
|
||||
{
|
||||
GSList *l;
|
||||
|
||||
for (l = data->self->choices; l; l = l->next, dialog_control_id++)
|
||||
{
|
||||
GtkFileChooserNativeChoice *choice = (GtkFileChooserNativeChoice*) l->data;
|
||||
@@ -742,6 +763,8 @@ filechooser_win32_thread (gpointer _data)
|
||||
hr = IFileDialog_QueryInterface (pfd, &IID_IFileDialogCustomize, (LPVOID *) &pfdc);
|
||||
if (SUCCEEDED (hr))
|
||||
{
|
||||
GSList *l;
|
||||
|
||||
for (l = data->self->choices; l; l = l->next)
|
||||
{
|
||||
GtkFileChooserNativeChoice *choice = (GtkFileChooserNativeChoice*) l->data;
|
||||
@@ -864,21 +887,24 @@ gtk_file_chooser_native_win32_show (GtkFileChooserNative *self)
|
||||
FilechooserWin32ThreadData *data;
|
||||
GtkWindow *transient_for;
|
||||
GtkFileChooserAction action;
|
||||
GSList *filters, *l;
|
||||
int n_filters, i;
|
||||
GListModel *filters;
|
||||
guint n_filters, i;
|
||||
|
||||
data = g_new0 (FilechooserWin32ThreadData, 1);
|
||||
|
||||
filters = gtk_file_chooser_list_filters (GTK_FILE_CHOOSER (self));
|
||||
n_filters = g_slist_length (filters);
|
||||
filters = gtk_file_chooser_get_filters (GTK_FILE_CHOOSER (self));
|
||||
n_filters = g_list_model_get_n_items (filters);
|
||||
if (n_filters > 0)
|
||||
{
|
||||
data->filters = g_new0 (COMDLG_FILTERSPEC, n_filters + 1);
|
||||
|
||||
for (l = filters, i = 0; l != NULL; l = l->next, i++)
|
||||
for (i = 0; i < n_filters; i++)
|
||||
{
|
||||
if (!file_filter_to_win32 (l->data, &data->filters[i]))
|
||||
GtkFileFilter *filter = g_list_model_get_item (filters, i);
|
||||
if (!file_filter_to_win32 (filter, &data->filters[i]))
|
||||
{
|
||||
g_object_unref (filter);
|
||||
g_object_unref (filters);
|
||||
filechooser_win32_thread_data_free (data);
|
||||
return FALSE;
|
||||
}
|
||||
@@ -889,12 +915,13 @@ gtk_file_chooser_native_win32_show (GtkFileChooserNative *self)
|
||||
{
|
||||
self->current_filter = NULL;
|
||||
}
|
||||
g_object_unref (filters);
|
||||
|
||||
self->mode_data = data;
|
||||
data->self = g_object_ref (self);
|
||||
|
||||
data->shortcut_files =
|
||||
gtk_file_chooser_list_shortcut_folders (GTK_FILE_CHOOSER (self->dialog));
|
||||
gtk_file_chooser_get_shortcut_folders (GTK_FILE_CHOOSER (self->dialog));
|
||||
|
||||
data->accept_label = translate_mnemonics (self->accept_label);
|
||||
data->cancel_label = translate_mnemonics (self->cancel_label);
|
||||
|
||||
+32
-25
@@ -58,34 +58,34 @@ struct _GtkFileChooserIface
|
||||
|
||||
/* Methods
|
||||
*/
|
||||
gboolean (*set_current_folder) (GtkFileChooser *chooser,
|
||||
GFile *file,
|
||||
GError **error);
|
||||
GFile * (*get_current_folder) (GtkFileChooser *chooser);
|
||||
void (*set_current_name) (GtkFileChooser *chooser,
|
||||
const gchar *name);
|
||||
gboolean (*set_current_folder) (GtkFileChooser *chooser,
|
||||
GFile *file,
|
||||
GError **error);
|
||||
GFile * (*get_current_folder) (GtkFileChooser *chooser);
|
||||
void (*set_current_name) (GtkFileChooser *chooser,
|
||||
const gchar *name);
|
||||
gchar * (*get_current_name) (GtkFileChooser *chooser);
|
||||
gboolean (*select_file) (GtkFileChooser *chooser,
|
||||
GFile *file,
|
||||
GError **error);
|
||||
void (*unselect_file) (GtkFileChooser *chooser,
|
||||
GFile *file);
|
||||
void (*select_all) (GtkFileChooser *chooser);
|
||||
void (*unselect_all) (GtkFileChooser *chooser);
|
||||
GSList * (*get_files) (GtkFileChooser *chooser);
|
||||
GtkFileSystem *(*get_file_system) (GtkFileChooser *chooser);
|
||||
void (*add_filter) (GtkFileChooser *chooser,
|
||||
GtkFileFilter *filter);
|
||||
void (*remove_filter) (GtkFileChooser *chooser,
|
||||
GtkFileFilter *filter);
|
||||
GSList * (*list_filters) (GtkFileChooser *chooser);
|
||||
gboolean (*select_file) (GtkFileChooser *chooser,
|
||||
GFile *file,
|
||||
GError **error);
|
||||
void (*unselect_file) (GtkFileChooser *chooser,
|
||||
GFile *file);
|
||||
void (*select_all) (GtkFileChooser *chooser);
|
||||
void (*unselect_all) (GtkFileChooser *chooser);
|
||||
GListModel * (*get_files) (GtkFileChooser *chooser);
|
||||
GtkFileSystem *(*get_file_system) (GtkFileChooser *chooser);
|
||||
void (*add_filter) (GtkFileChooser *chooser,
|
||||
GtkFileFilter *filter);
|
||||
void (*remove_filter) (GtkFileChooser *chooser,
|
||||
GtkFileFilter *filter);
|
||||
GListModel * (*get_filters) (GtkFileChooser *chooser);
|
||||
gboolean (*add_shortcut_folder) (GtkFileChooser *chooser,
|
||||
GFile *file,
|
||||
GError **error);
|
||||
GFile *file,
|
||||
GError **error);
|
||||
gboolean (*remove_shortcut_folder) (GtkFileChooser *chooser,
|
||||
GFile *file,
|
||||
GError **error);
|
||||
GSList * (*list_shortcut_folders) (GtkFileChooser *chooser);
|
||||
GFile *file,
|
||||
GError **error);
|
||||
GListModel * (*get_shortcut_folders) (GtkFileChooser *chooser);
|
||||
|
||||
/* Signals
|
||||
*/
|
||||
@@ -111,6 +111,13 @@ struct _GtkFileChooserIface
|
||||
|
||||
GtkFileSystem *_gtk_file_chooser_get_file_system (GtkFileChooser *chooser);
|
||||
|
||||
void gtk_file_chooser_select_all (GtkFileChooser *chooser);
|
||||
void gtk_file_chooser_unselect_all (GtkFileChooser *chooser);
|
||||
gboolean gtk_file_chooser_select_file (GtkFileChooser *chooser,
|
||||
GFile *file,
|
||||
GError **error);
|
||||
void gtk_file_chooser_unselect_file (GtkFileChooser *chooser,
|
||||
GFile *file);
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_FILE_CHOOSER_PRIVATE_H__ */
|
||||
|
||||
+26
-53
@@ -39,29 +39,23 @@ static void delegate_unselect_file (GtkFileChooser *choose
|
||||
GFile *file);
|
||||
static void delegate_select_all (GtkFileChooser *chooser);
|
||||
static void delegate_unselect_all (GtkFileChooser *chooser);
|
||||
static GSList * delegate_get_files (GtkFileChooser *chooser);
|
||||
static GListModel * delegate_get_files (GtkFileChooser *chooser);
|
||||
static GtkFileSystem *delegate_get_file_system (GtkFileChooser *chooser);
|
||||
static void delegate_add_filter (GtkFileChooser *chooser,
|
||||
GtkFileFilter *filter);
|
||||
static void delegate_remove_filter (GtkFileChooser *chooser,
|
||||
GtkFileFilter *filter);
|
||||
static GSList * delegate_list_filters (GtkFileChooser *chooser);
|
||||
static GListModel * delegate_get_filters (GtkFileChooser *chooser);
|
||||
static gboolean delegate_add_shortcut_folder (GtkFileChooser *chooser,
|
||||
GFile *file,
|
||||
GError **error);
|
||||
static gboolean delegate_remove_shortcut_folder (GtkFileChooser *chooser,
|
||||
GFile *file,
|
||||
GError **error);
|
||||
static GSList * delegate_list_shortcut_folders (GtkFileChooser *chooser);
|
||||
static GListModel * delegate_get_shortcut_folders (GtkFileChooser *chooser);
|
||||
static void delegate_notify (GObject *object,
|
||||
GParamSpec *pspec,
|
||||
gpointer data);
|
||||
static void delegate_current_folder_changed (GtkFileChooser *chooser,
|
||||
gpointer data);
|
||||
static void delegate_selection_changed (GtkFileChooser *chooser,
|
||||
gpointer data);
|
||||
static void delegate_file_activated (GtkFileChooser *chooser,
|
||||
gpointer data);
|
||||
|
||||
static void delegate_add_choice (GtkFileChooser *chooser,
|
||||
const char *id,
|
||||
@@ -92,17 +86,23 @@ void
|
||||
_gtk_file_chooser_install_properties (GObjectClass *klass)
|
||||
{
|
||||
g_object_class_override_property (klass,
|
||||
GTK_FILE_CHOOSER_PROP_ACTION,
|
||||
"action");
|
||||
GTK_FILE_CHOOSER_PROP_ACTION,
|
||||
"action");
|
||||
g_object_class_override_property (klass,
|
||||
GTK_FILE_CHOOSER_PROP_FILTER,
|
||||
"filter");
|
||||
GTK_FILE_CHOOSER_PROP_FILTER,
|
||||
"filter");
|
||||
g_object_class_override_property (klass,
|
||||
GTK_FILE_CHOOSER_PROP_SELECT_MULTIPLE,
|
||||
"select-multiple");
|
||||
GTK_FILE_CHOOSER_PROP_SELECT_MULTIPLE,
|
||||
"select-multiple");
|
||||
g_object_class_override_property (klass,
|
||||
GTK_FILE_CHOOSER_PROP_CREATE_FOLDERS,
|
||||
"create-folders");
|
||||
GTK_FILE_CHOOSER_PROP_CREATE_FOLDERS,
|
||||
"create-folders");
|
||||
g_object_class_override_property (klass,
|
||||
GTK_FILE_CHOOSER_PROP_FILTERS,
|
||||
"filters");
|
||||
g_object_class_override_property (klass,
|
||||
GTK_FILE_CHOOSER_PROP_SHORTCUT_FOLDERS,
|
||||
"shortcut-folders");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -131,10 +131,10 @@ _gtk_file_chooser_delegate_iface_init (GtkFileChooserIface *iface)
|
||||
iface->get_file_system = delegate_get_file_system;
|
||||
iface->add_filter = delegate_add_filter;
|
||||
iface->remove_filter = delegate_remove_filter;
|
||||
iface->list_filters = delegate_list_filters;
|
||||
iface->get_filters = delegate_get_filters;
|
||||
iface->add_shortcut_folder = delegate_add_shortcut_folder;
|
||||
iface->remove_shortcut_folder = delegate_remove_shortcut_folder;
|
||||
iface->list_shortcut_folders = delegate_list_shortcut_folders;
|
||||
iface->get_shortcut_folders = delegate_get_shortcut_folders;
|
||||
iface->add_choice = delegate_add_choice;
|
||||
iface->remove_choice = delegate_remove_choice;
|
||||
iface->set_choice = delegate_set_choice;
|
||||
@@ -162,12 +162,6 @@ _gtk_file_chooser_set_delegate (GtkFileChooser *receiver,
|
||||
g_object_set_data (G_OBJECT (receiver), I_("gtk-file-chooser-delegate"), delegate);
|
||||
g_signal_connect (delegate, "notify",
|
||||
G_CALLBACK (delegate_notify), receiver);
|
||||
g_signal_connect (delegate, "current-folder-changed",
|
||||
G_CALLBACK (delegate_current_folder_changed), receiver);
|
||||
g_signal_connect (delegate, "selection-changed",
|
||||
G_CALLBACK (delegate_selection_changed), receiver);
|
||||
g_signal_connect (delegate, "file-activated",
|
||||
G_CALLBACK (delegate_file_activated), receiver);
|
||||
}
|
||||
|
||||
GQuark
|
||||
@@ -215,7 +209,7 @@ delegate_unselect_all (GtkFileChooser *chooser)
|
||||
gtk_file_chooser_unselect_all (get_delegate (chooser));
|
||||
}
|
||||
|
||||
static GSList *
|
||||
static GListModel *
|
||||
delegate_get_files (GtkFileChooser *chooser)
|
||||
{
|
||||
return gtk_file_chooser_get_files (get_delegate (chooser));
|
||||
@@ -241,10 +235,10 @@ delegate_remove_filter (GtkFileChooser *chooser,
|
||||
gtk_file_chooser_remove_filter (get_delegate (chooser), filter);
|
||||
}
|
||||
|
||||
static GSList *
|
||||
delegate_list_filters (GtkFileChooser *chooser)
|
||||
static GListModel *
|
||||
delegate_get_filters (GtkFileChooser *chooser)
|
||||
{
|
||||
return gtk_file_chooser_list_filters (get_delegate (chooser));
|
||||
return gtk_file_chooser_get_filters (get_delegate (chooser));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -263,10 +257,10 @@ delegate_remove_shortcut_folder (GtkFileChooser *chooser,
|
||||
return gtk_file_chooser_remove_shortcut_folder (get_delegate (chooser), file, error);
|
||||
}
|
||||
|
||||
static GSList *
|
||||
delegate_list_shortcut_folders (GtkFileChooser *chooser)
|
||||
static GListModel *
|
||||
delegate_get_shortcut_folders (GtkFileChooser *chooser)
|
||||
{
|
||||
return gtk_file_chooser_list_shortcut_folders (get_delegate (chooser));
|
||||
return gtk_file_chooser_get_shortcut_folders (get_delegate (chooser));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -309,27 +303,6 @@ delegate_notify (GObject *object,
|
||||
g_object_notify (data, pspec->name);
|
||||
}
|
||||
|
||||
static void
|
||||
delegate_selection_changed (GtkFileChooser *chooser,
|
||||
gpointer data)
|
||||
{
|
||||
g_signal_emit_by_name (data, "selection-changed");
|
||||
}
|
||||
|
||||
static void
|
||||
delegate_current_folder_changed (GtkFileChooser *chooser,
|
||||
gpointer data)
|
||||
{
|
||||
g_signal_emit_by_name (data, "current-folder-changed");
|
||||
}
|
||||
|
||||
static void
|
||||
delegate_file_activated (GtkFileChooser *chooser,
|
||||
gpointer data)
|
||||
{
|
||||
g_signal_emit_by_name (data, "file-activated");
|
||||
}
|
||||
|
||||
GSettings *
|
||||
_gtk_file_chooser_get_settings_for_widget (GtkWidget *widget)
|
||||
{
|
||||
|
||||
@@ -32,7 +32,9 @@ typedef enum {
|
||||
GTK_FILE_CHOOSER_PROP_FILTER,
|
||||
GTK_FILE_CHOOSER_PROP_SELECT_MULTIPLE,
|
||||
GTK_FILE_CHOOSER_PROP_CREATE_FOLDERS,
|
||||
GTK_FILE_CHOOSER_PROP_LAST = GTK_FILE_CHOOSER_PROP_CREATE_FOLDERS
|
||||
GTK_FILE_CHOOSER_PROP_FILTERS,
|
||||
GTK_FILE_CHOOSER_PROP_SHORTCUT_FOLDERS,
|
||||
GTK_FILE_CHOOSER_PROP_LAST = GTK_FILE_CHOOSER_PROP_SHORTCUT_FOLDERS
|
||||
} GtkFileChooserProp;
|
||||
|
||||
void _gtk_file_chooser_install_properties (GObjectClass *klass);
|
||||
|
||||
+131
-54
@@ -479,20 +479,20 @@ static void gtk_file_chooser_widget_unselect_file (GtkF
|
||||
GFile *file);
|
||||
static void gtk_file_chooser_widget_select_all (GtkFileChooser *chooser);
|
||||
static void gtk_file_chooser_widget_unselect_all (GtkFileChooser *chooser);
|
||||
static GSList * gtk_file_chooser_widget_get_files (GtkFileChooser *chooser);
|
||||
static GListModel * gtk_file_chooser_widget_get_files (GtkFileChooser *chooser);
|
||||
static GtkFileSystem *gtk_file_chooser_widget_get_file_system (GtkFileChooser *chooser);
|
||||
static void gtk_file_chooser_widget_add_filter (GtkFileChooser *chooser,
|
||||
GtkFileFilter *filter);
|
||||
static void gtk_file_chooser_widget_remove_filter (GtkFileChooser *chooser,
|
||||
GtkFileFilter *filter);
|
||||
static GSList * gtk_file_chooser_widget_list_filters (GtkFileChooser *chooser);
|
||||
static GListModel * gtk_file_chooser_widget_get_filters (GtkFileChooser *chooser);
|
||||
static gboolean gtk_file_chooser_widget_add_shortcut_folder (GtkFileChooser *chooser,
|
||||
GFile *file,
|
||||
GError **error);
|
||||
static gboolean gtk_file_chooser_widget_remove_shortcut_folder (GtkFileChooser *chooser,
|
||||
GFile *file,
|
||||
GError **error);
|
||||
static GSList * gtk_file_chooser_widget_list_shortcut_folders (GtkFileChooser *chooser);
|
||||
static GListModel * gtk_file_chooser_widget_get_shortcut_folders (GtkFileChooser *chooser);
|
||||
|
||||
static gboolean gtk_file_chooser_widget_should_respond (GtkFileChooserEmbed *chooser_embed);
|
||||
static void gtk_file_chooser_widget_initial_focus (GtkFileChooserEmbed *chooser_embed);
|
||||
@@ -619,10 +619,10 @@ gtk_file_chooser_widget_iface_init (GtkFileChooserIface *iface)
|
||||
iface->get_current_name = gtk_file_chooser_widget_get_current_name;
|
||||
iface->add_filter = gtk_file_chooser_widget_add_filter;
|
||||
iface->remove_filter = gtk_file_chooser_widget_remove_filter;
|
||||
iface->list_filters = gtk_file_chooser_widget_list_filters;
|
||||
iface->get_filters = gtk_file_chooser_widget_get_filters;
|
||||
iface->add_shortcut_folder = gtk_file_chooser_widget_add_shortcut_folder;
|
||||
iface->remove_shortcut_folder = gtk_file_chooser_widget_remove_shortcut_folder;
|
||||
iface->list_shortcut_folders = gtk_file_chooser_widget_list_shortcut_folders;
|
||||
iface->get_shortcut_folders = gtk_file_chooser_widget_get_shortcut_folders;
|
||||
iface->add_choice = gtk_file_chooser_widget_add_choice;
|
||||
iface->remove_choice = gtk_file_chooser_widget_remove_choice;
|
||||
iface->set_choice = gtk_file_chooser_widget_set_choice;
|
||||
@@ -2220,14 +2220,66 @@ set_icon_cell_renderer_fixed_size (GtkFileChooserWidget *impl)
|
||||
ypad * 2 + ICON_SIZE);
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
get_accept_action_widget (GtkDialog *dialog,
|
||||
gboolean sensitive_only)
|
||||
{
|
||||
gint response[] = {
|
||||
GTK_RESPONSE_ACCEPT,
|
||||
GTK_RESPONSE_OK,
|
||||
GTK_RESPONSE_YES,
|
||||
GTK_RESPONSE_APPLY
|
||||
};
|
||||
gint i;
|
||||
GtkWidget *widget;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (response); i++)
|
||||
{
|
||||
widget = gtk_dialog_get_widget_for_response (dialog, response[i]);
|
||||
if (widget)
|
||||
{
|
||||
if (!sensitive_only)
|
||||
return widget;
|
||||
|
||||
if (gtk_widget_is_sensitive (widget))
|
||||
return widget;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
update_default (GtkFileChooserWidget *impl)
|
||||
{
|
||||
GtkWidget *dialog;
|
||||
GtkWidget *button;
|
||||
GListModel *files;
|
||||
gboolean sensitive;
|
||||
|
||||
dialog = gtk_widget_get_ancestor (GTK_WIDGET (impl), GTK_TYPE_DIALOG);
|
||||
if (dialog == NULL)
|
||||
return;
|
||||
|
||||
button = get_accept_action_widget (GTK_DIALOG (dialog), FALSE);
|
||||
if (button == NULL)
|
||||
return;
|
||||
|
||||
files = gtk_file_chooser_get_files (GTK_FILE_CHOOSER (impl));
|
||||
sensitive = (g_list_model_get_n_items (files) > 0);
|
||||
gtk_widget_set_sensitive (button, sensitive);
|
||||
|
||||
g_object_unref (files);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
location_changed_timeout_cb (gpointer user_data)
|
||||
{
|
||||
GtkFileChooserWidget *impl = user_data;
|
||||
|
||||
gtk_file_chooser_unselect_all (GTK_FILE_CHOOSER (impl));
|
||||
g_signal_emit_by_name (impl, "selection-changed", 0);
|
||||
|
||||
update_default (impl);
|
||||
impl->location_changed_id = 0;
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
@@ -3072,6 +3124,14 @@ gtk_file_chooser_widget_get_property (GObject *object,
|
||||
g_value_set_boolean (value, impl->create_folders);
|
||||
break;
|
||||
|
||||
case GTK_FILE_CHOOSER_PROP_FILTERS:
|
||||
g_value_set_object (value, impl->filters);
|
||||
break;
|
||||
|
||||
case GTK_FILE_CHOOSER_PROP_SHORTCUT_FOLDERS:
|
||||
g_value_take_object (value, gtk_file_chooser_get_shortcut_folders (GTK_FILE_CHOOSER (impl)));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@@ -3429,25 +3489,27 @@ set_startup_mode (GtkFileChooserWidget *impl)
|
||||
static gboolean
|
||||
shortcut_exists (GtkFileChooserWidget *impl, GFile *needle)
|
||||
{
|
||||
GSList *haystack;
|
||||
GSList *l;
|
||||
GListModel *haystack;
|
||||
guint n, i;
|
||||
gboolean exists;
|
||||
|
||||
exists = FALSE;
|
||||
|
||||
haystack = gtk_places_sidebar_list_shortcuts (GTK_PLACES_SIDEBAR (impl->places_sidebar));
|
||||
for (l = haystack; l; l = l->next)
|
||||
haystack = gtk_places_sidebar_get_shortcuts (GTK_PLACES_SIDEBAR (impl->places_sidebar));
|
||||
n = g_list_model_get_n_items (haystack);
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
GFile *hay;
|
||||
GFile *hay = g_list_model_get_item (haystack, i);
|
||||
|
||||
hay = G_FILE (l->data);
|
||||
if (g_file_equal (hay, needle))
|
||||
{
|
||||
g_object_unref (hay);
|
||||
exists = TRUE;
|
||||
break;
|
||||
}
|
||||
g_object_unref (hay);
|
||||
}
|
||||
g_slist_free_full (haystack, g_object_unref);
|
||||
g_object_unref (haystack);
|
||||
|
||||
return exists;
|
||||
}
|
||||
@@ -5074,9 +5136,7 @@ update_current_folder_get_info_cb (GCancellable *cancellable,
|
||||
|
||||
g_object_notify (G_OBJECT (impl), "subtitle");
|
||||
|
||||
g_signal_emit_by_name (impl, "current-folder-changed", 0);
|
||||
|
||||
g_signal_emit_by_name (impl, "selection-changed", 0);
|
||||
update_default (impl);
|
||||
|
||||
out:
|
||||
g_object_unref (data->impl);
|
||||
@@ -5398,7 +5458,7 @@ check_save_entry (GtkFileChooserWidget *impl,
|
||||
|
||||
struct get_files_closure {
|
||||
GtkFileChooserWidget *impl;
|
||||
GSList *result;
|
||||
GListStore *result;
|
||||
GFile *file_from_entry;
|
||||
};
|
||||
|
||||
@@ -5415,10 +5475,25 @@ get_files_foreach (GtkTreeModel *model,
|
||||
file = _gtk_file_system_model_get_file (fs_model, iter);
|
||||
|
||||
if (!info->file_from_entry || !g_file_equal (info->file_from_entry, file))
|
||||
info->result = g_slist_prepend (info->result, g_object_ref (file));
|
||||
g_list_store_append (info->result, file);
|
||||
}
|
||||
|
||||
static GSList *
|
||||
static GListModel *
|
||||
get_selected_files_as_model (GtkFileChooserWidget *impl)
|
||||
{
|
||||
GListStore *store;
|
||||
GSList *files, *l;
|
||||
|
||||
store = g_list_store_new (G_TYPE_FILE);
|
||||
files = get_selected_files (impl);
|
||||
for (l = files; l; l = l->next)
|
||||
g_list_store_append (store, l->data);
|
||||
g_slist_free_full (files, g_object_unref);
|
||||
|
||||
return G_LIST_MODEL (store);
|
||||
}
|
||||
|
||||
static GListModel *
|
||||
gtk_file_chooser_widget_get_files (GtkFileChooser *chooser)
|
||||
{
|
||||
GtkFileChooserWidget *impl = GTK_FILE_CHOOSER_WIDGET (chooser);
|
||||
@@ -5427,12 +5502,8 @@ gtk_file_chooser_widget_get_files (GtkFileChooser *chooser)
|
||||
GtkWidget *current_focus;
|
||||
gboolean file_list_seen;
|
||||
|
||||
info.impl = impl;
|
||||
info.result = NULL;
|
||||
info.file_from_entry = NULL;
|
||||
|
||||
if (impl->operation_mode == OPERATION_MODE_SEARCH)
|
||||
return get_selected_files (impl);
|
||||
return get_selected_files_as_model (impl);
|
||||
|
||||
if (impl->operation_mode == OPERATION_MODE_RECENT)
|
||||
{
|
||||
@@ -5442,9 +5513,13 @@ gtk_file_chooser_widget_get_files (GtkFileChooser *chooser)
|
||||
goto file_entry;
|
||||
}
|
||||
else
|
||||
return get_selected_files (impl);
|
||||
return get_selected_files_as_model (impl);
|
||||
}
|
||||
|
||||
info.impl = impl;
|
||||
info.result = g_list_store_new (G_TYPE_FILE);
|
||||
info.file_from_entry = NULL;
|
||||
|
||||
toplevel = get_toplevel (GTK_WIDGET (impl));
|
||||
if (toplevel)
|
||||
current_focus = gtk_root_get_focus (GTK_ROOT (toplevel));
|
||||
@@ -5488,7 +5563,7 @@ gtk_file_chooser_widget_get_files (GtkFileChooser *chooser)
|
||||
return NULL;
|
||||
|
||||
if (info.file_from_entry)
|
||||
info.result = g_slist_prepend (info.result, info.file_from_entry);
|
||||
g_list_store_append (info.result, info.file_from_entry);
|
||||
else if (!file_list_seen)
|
||||
goto file_list;
|
||||
else
|
||||
@@ -5520,10 +5595,10 @@ gtk_file_chooser_widget_get_files (GtkFileChooser *chooser)
|
||||
current_folder = gtk_file_chooser_get_current_folder (chooser);
|
||||
|
||||
if (current_folder)
|
||||
info.result = g_slist_prepend (info.result, current_folder);
|
||||
g_list_store_append (info.result, current_folder);
|
||||
}
|
||||
|
||||
return g_slist_reverse (info.result);
|
||||
return G_LIST_MODEL (info.result);
|
||||
}
|
||||
|
||||
static GtkFileSystem *
|
||||
@@ -5564,6 +5639,8 @@ gtk_file_chooser_widget_add_filter (GtkFileChooser *chooser,
|
||||
set_current_filter (impl, filter);
|
||||
|
||||
show_filters (impl, TRUE);
|
||||
|
||||
g_object_notify (G_OBJECT (chooser), "filters");
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -5597,25 +5674,16 @@ gtk_file_chooser_widget_remove_filter (GtkFileChooser *chooser,
|
||||
|
||||
if (!impl->filters)
|
||||
show_filters (impl, FALSE);
|
||||
|
||||
g_object_notify (G_OBJECT (chooser), "filters");
|
||||
}
|
||||
|
||||
static GSList *
|
||||
gtk_file_chooser_widget_list_filters (GtkFileChooser *chooser)
|
||||
static GListModel *
|
||||
gtk_file_chooser_widget_get_filters (GtkFileChooser *chooser)
|
||||
{
|
||||
GtkFileChooserWidget *impl = GTK_FILE_CHOOSER_WIDGET (chooser);
|
||||
GSList *filters;
|
||||
guint i;
|
||||
|
||||
filters = NULL;
|
||||
|
||||
for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (impl->filters)); i++)
|
||||
{
|
||||
GtkFileFilter *filter = g_list_model_get_item (G_LIST_MODEL (impl->filters), i);
|
||||
filters = g_slist_append (filters, filter);
|
||||
g_object_unref (filter);
|
||||
}
|
||||
|
||||
return filters;
|
||||
return G_LIST_MODEL (g_object_ref (impl->filters));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -5626,6 +5694,9 @@ gtk_file_chooser_widget_add_shortcut_folder (GtkFileChooser *chooser,
|
||||
GtkFileChooserWidget *impl = GTK_FILE_CHOOSER_WIDGET (chooser);
|
||||
|
||||
gtk_places_sidebar_add_shortcut (GTK_PLACES_SIDEBAR (impl->places_sidebar), file);
|
||||
|
||||
g_object_notify (G_OBJECT (chooser), "shortcut-folders");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -5637,15 +5708,18 @@ gtk_file_chooser_widget_remove_shortcut_folder (GtkFileChooser *chooser,
|
||||
GtkFileChooserWidget *impl = GTK_FILE_CHOOSER_WIDGET (chooser);
|
||||
|
||||
gtk_places_sidebar_remove_shortcut (GTK_PLACES_SIDEBAR (impl->places_sidebar), file);
|
||||
|
||||
g_object_notify (G_OBJECT (chooser), "shortcut-folders");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GSList *
|
||||
gtk_file_chooser_widget_list_shortcut_folders (GtkFileChooser *chooser)
|
||||
static GListModel *
|
||||
gtk_file_chooser_widget_get_shortcut_folders (GtkFileChooser *chooser)
|
||||
{
|
||||
GtkFileChooserWidget *impl = GTK_FILE_CHOOSER_WIDGET (chooser);
|
||||
|
||||
return gtk_places_sidebar_list_shortcuts (GTK_PLACES_SIDEBAR (impl->places_sidebar));
|
||||
return gtk_places_sidebar_get_shortcuts (GTK_PLACES_SIDEBAR (impl->places_sidebar));
|
||||
}
|
||||
|
||||
struct switch_folder_closure {
|
||||
@@ -6134,18 +6208,18 @@ location_popup_on_paste_handler (GtkFileChooserWidget *impl)
|
||||
static void
|
||||
add_selection_to_recent_list (GtkFileChooserWidget *impl)
|
||||
{
|
||||
GSList *files;
|
||||
GSList *l;
|
||||
GListModel *files;
|
||||
guint i, n;
|
||||
|
||||
files = gtk_file_chooser_widget_get_files (GTK_FILE_CHOOSER (impl));
|
||||
|
||||
|
||||
if (!impl->recent_manager)
|
||||
impl->recent_manager = gtk_recent_manager_get_default ();
|
||||
|
||||
for (l = files; l; l = l->next)
|
||||
n = g_list_model_get_n_items (files);
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
GFile *file = l->data;
|
||||
GFile *file = g_list_model_get_item (files, i);
|
||||
char *uri;
|
||||
|
||||
uri = g_file_get_uri (file);
|
||||
@@ -6154,9 +6228,11 @@ add_selection_to_recent_list (GtkFileChooserWidget *impl)
|
||||
gtk_recent_manager_add_item (impl->recent_manager, uri);
|
||||
g_free (uri);
|
||||
}
|
||||
|
||||
g_object_unref (file);
|
||||
}
|
||||
|
||||
g_slist_free_full (files, g_object_unref);
|
||||
g_object_unref (files);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -6933,6 +7009,8 @@ filter_combo_changed (GtkDropDown *dropdown,
|
||||
|
||||
new_filter = gtk_drop_down_get_selected_item (dropdown);
|
||||
|
||||
set_current_filter (impl, new_filter);
|
||||
|
||||
if (impl->location_entry != NULL)
|
||||
_gtk_file_chooser_entry_set_file_filter (GTK_FILE_CHOOSER_ENTRY (impl->location_entry),
|
||||
new_filter);
|
||||
@@ -6978,8 +7056,7 @@ list_selection_changed (GtkTreeSelection *selection,
|
||||
update_chooser_entry (impl);
|
||||
|
||||
location_bar_update (impl);
|
||||
|
||||
g_signal_emit_by_name (impl, "selection-changed", 0);
|
||||
update_default (impl);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -7031,7 +7108,7 @@ list_row_activated (GtkTreeView *tree_view,
|
||||
|
||||
if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
|
||||
impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
|
||||
g_signal_emit_by_name (impl, "file-activated");
|
||||
gtk_widget_activate_default (GTK_WIDGET (impl));
|
||||
|
||||
out:
|
||||
|
||||
|
||||
+336
-373
File diff suppressed because it is too large
Load Diff
+13
-78
@@ -33,99 +33,34 @@ G_BEGIN_DECLS
|
||||
#define GTK_IS_FILE_FILTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_FILE_FILTER))
|
||||
|
||||
typedef struct _GtkFileFilter GtkFileFilter;
|
||||
typedef struct _GtkFileFilterInfo GtkFileFilterInfo;
|
||||
|
||||
/**
|
||||
* GtkFileFilterFlags:
|
||||
* @GTK_FILE_FILTER_FILENAME: the filename of the file being tested
|
||||
* @GTK_FILE_FILTER_URI: the URI for the file being tested
|
||||
* @GTK_FILE_FILTER_DISPLAY_NAME: the string that will be used to
|
||||
* display the file in the file chooser
|
||||
* @GTK_FILE_FILTER_MIME_TYPE: the mime type of the file
|
||||
*
|
||||
* These flags indicate what parts of a #GtkFileFilterInfo struct
|
||||
* are filled or need to be filled.
|
||||
*/
|
||||
typedef enum {
|
||||
GTK_FILE_FILTER_FILENAME = 1 << 0,
|
||||
GTK_FILE_FILTER_URI = 1 << 1,
|
||||
GTK_FILE_FILTER_DISPLAY_NAME = 1 << 2,
|
||||
GTK_FILE_FILTER_MIME_TYPE = 1 << 3
|
||||
} GtkFileFilterFlags;
|
||||
|
||||
/**
|
||||
* GtkFileFilterFunc:
|
||||
* @filter_info: a #GtkFileFilterInfo that is filled according
|
||||
* to the @needed flags passed to gtk_file_filter_add_custom()
|
||||
* @data: (closure): user data passed to gtk_file_filter_add_custom()
|
||||
*
|
||||
* The type of function that is used with custom filters, see
|
||||
* gtk_file_filter_add_custom().
|
||||
*
|
||||
* Returns: %TRUE if the file should be displayed
|
||||
*/
|
||||
typedef gboolean (*GtkFileFilterFunc) (const GtkFileFilterInfo *filter_info,
|
||||
gpointer data);
|
||||
|
||||
/**
|
||||
* GtkFileFilterInfo:
|
||||
* @contains: Flags indicating which of the following fields need
|
||||
* are filled
|
||||
* @filename: the filename of the file being tested
|
||||
* @uri: the URI for the file being tested
|
||||
* @display_name: the string that will be used to display the file
|
||||
* in the file chooser
|
||||
* @mime_type: the mime type of the file
|
||||
*
|
||||
* A #GtkFileFilterInfo is used to pass information about the
|
||||
* tested file to gtk_file_filter_filter().
|
||||
*/
|
||||
struct _GtkFileFilterInfo
|
||||
{
|
||||
GtkFileFilterFlags contains;
|
||||
|
||||
const gchar *filename;
|
||||
const gchar *uri;
|
||||
const gchar *display_name;
|
||||
const gchar *mime_type;
|
||||
};
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gtk_file_filter_get_type (void) G_GNUC_CONST;
|
||||
GType gtk_file_filter_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkFileFilter * gtk_file_filter_new (void);
|
||||
GtkFileFilter * gtk_file_filter_new (void);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_file_filter_set_name (GtkFileFilter *filter,
|
||||
const gchar *name);
|
||||
void gtk_file_filter_set_name (GtkFileFilter *filter,
|
||||
const char *name);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
const gchar * gtk_file_filter_get_name (GtkFileFilter *filter);
|
||||
const char * gtk_file_filter_get_name (GtkFileFilter *filter);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_file_filter_add_mime_type (GtkFileFilter *filter,
|
||||
const gchar *mime_type);
|
||||
void gtk_file_filter_add_mime_type (GtkFileFilter *filter,
|
||||
const char *mime_type);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_file_filter_add_pattern (GtkFileFilter *filter,
|
||||
const gchar *pattern);
|
||||
void gtk_file_filter_add_pattern (GtkFileFilter *filter,
|
||||
const char *pattern);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_file_filter_add_pixbuf_formats (GtkFileFilter *filter);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_file_filter_add_custom (GtkFileFilter *filter,
|
||||
GtkFileFilterFlags needed,
|
||||
GtkFileFilterFunc func,
|
||||
gpointer data,
|
||||
GDestroyNotify notify);
|
||||
void gtk_file_filter_add_pixbuf_formats (GtkFileFilter *filter);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkFileFilterFlags gtk_file_filter_get_needed (GtkFileFilter *filter);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_file_filter_filter (GtkFileFilter *filter,
|
||||
const GtkFileFilterInfo *filter_info);
|
||||
const char ** gtk_file_filter_get_attributes (GtkFileFilter *filter);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GVariant *gtk_file_filter_to_gvariant (GtkFileFilter *filter);
|
||||
GVariant * gtk_file_filter_to_gvariant (GtkFileFilter *filter);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkFileFilter *gtk_file_filter_new_from_gvariant (GVariant *variant);
|
||||
GtkFileFilter * gtk_file_filter_new_from_gvariant (GVariant *variant);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "gtktreedatalist.h"
|
||||
#include "gtktreednd.h"
|
||||
#include "gtktreemodel.h"
|
||||
#include "gtkfilter.h"
|
||||
|
||||
/*** Structure: how GtkFileSystemModel works
|
||||
*
|
||||
@@ -375,12 +376,6 @@ static gboolean
|
||||
node_should_be_filtered_out (GtkFileSystemModel *model, guint id)
|
||||
{
|
||||
FileModelNode *node = get_node (model, id);
|
||||
GtkFileFilterInfo filter_info = { 0, };
|
||||
GtkFileFilterFlags required;
|
||||
gboolean result;
|
||||
char *mime_type = NULL;
|
||||
char *filename = NULL;
|
||||
char *uri = NULL;
|
||||
|
||||
if (node->info == NULL)
|
||||
return TRUE;
|
||||
@@ -388,57 +383,10 @@ node_should_be_filtered_out (GtkFileSystemModel *model, guint id)
|
||||
if (model->filter == NULL)
|
||||
return FALSE;
|
||||
|
||||
/* fill info */
|
||||
required = gtk_file_filter_get_needed (model->filter);
|
||||
if (!g_file_info_has_attribute (node->info, "standard::file"))
|
||||
g_file_info_set_attribute_object (node->info, "standard::file", G_OBJECT (node->file));
|
||||
|
||||
filter_info.contains = GTK_FILE_FILTER_DISPLAY_NAME;
|
||||
filter_info.display_name = g_file_info_get_display_name (node->info);
|
||||
|
||||
if (required & GTK_FILE_FILTER_MIME_TYPE)
|
||||
{
|
||||
const char *s = g_file_info_get_content_type (node->info);
|
||||
|
||||
if (!s)
|
||||
s = g_file_info_get_attribute_string (node->info, G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE);
|
||||
|
||||
if (s)
|
||||
{
|
||||
mime_type = g_content_type_get_mime_type (s);
|
||||
if (mime_type)
|
||||
{
|
||||
filter_info.mime_type = mime_type;
|
||||
filter_info.contains |= GTK_FILE_FILTER_MIME_TYPE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (required & GTK_FILE_FILTER_FILENAME)
|
||||
{
|
||||
filename = g_file_get_path (node->file);
|
||||
if (filename)
|
||||
{
|
||||
filter_info.filename = filename;
|
||||
filter_info.contains |= GTK_FILE_FILTER_FILENAME;
|
||||
}
|
||||
}
|
||||
|
||||
if (required & GTK_FILE_FILTER_URI)
|
||||
{
|
||||
uri = g_file_get_uri (node->file);
|
||||
if (uri)
|
||||
{
|
||||
filter_info.uri = uri;
|
||||
filter_info.contains |= GTK_FILE_FILTER_URI;
|
||||
}
|
||||
}
|
||||
|
||||
result = !gtk_file_filter_filter (model->filter, &filter_info);
|
||||
|
||||
g_free (mime_type);
|
||||
g_free (filename);
|
||||
g_free (uri);
|
||||
|
||||
return result;
|
||||
return !gtk_filter_match (GTK_FILTER (model->filter), node->info);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
||||
+17
-56
@@ -45,7 +45,6 @@ enum {
|
||||
PROP_0,
|
||||
PROP_FILTER,
|
||||
PROP_INCREMENTAL,
|
||||
PROP_ITEM_TYPE,
|
||||
PROP_MODEL,
|
||||
PROP_PENDING,
|
||||
NUM_PROPERTIES
|
||||
@@ -55,7 +54,6 @@ struct _GtkFilterListModel
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
GType item_type;
|
||||
GListModel *model;
|
||||
GtkFilter *filter;
|
||||
GtkFilterMatch strictness;
|
||||
@@ -76,9 +74,7 @@ static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
|
||||
static GType
|
||||
gtk_filter_list_model_get_item_type (GListModel *list)
|
||||
{
|
||||
GtkFilterListModel *self = GTK_FILTER_LIST_MODEL (list);
|
||||
|
||||
return self->item_type;
|
||||
return G_TYPE_OBJECT;
|
||||
}
|
||||
|
||||
static guint
|
||||
@@ -182,7 +178,7 @@ gtk_filter_list_model_run_filter (GtkFilterListModel *self,
|
||||
}
|
||||
|
||||
if (more)
|
||||
gtk_bitset_remove_range_closed (self->pending, 0, pos);
|
||||
gtk_bitset_remove_range_closed (self->pending, 0, pos - 1);
|
||||
else
|
||||
g_clear_pointer (&self->pending, gtk_bitset_unref);
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_PENDING]);
|
||||
@@ -306,16 +302,21 @@ gtk_filter_list_model_items_changed_cb (GListModel *model,
|
||||
else
|
||||
filter_removed = 0;
|
||||
|
||||
gtk_bitset_slice (self->matches, position, removed, added);
|
||||
gtk_bitset_splice (self->matches, position, removed, added);
|
||||
if (self->pending)
|
||||
gtk_bitset_slice (self->pending, position, removed, added);
|
||||
gtk_bitset_splice (self->pending, position, removed, added);
|
||||
|
||||
gtk_filter_list_model_start_filtering (self, gtk_bitset_new_range (position, added));
|
||||
filter_added = gtk_bitset_get_size_in_range (self->matches, position, position + added - 1);
|
||||
if (added > 0)
|
||||
{
|
||||
gtk_filter_list_model_start_filtering (self, gtk_bitset_new_range (position, added));
|
||||
filter_added = gtk_bitset_get_size_in_range (self->matches, position, position + added - 1);
|
||||
}
|
||||
else
|
||||
filter_added = 0;
|
||||
|
||||
if (filter_removed > 0 || filter_added > 0)
|
||||
g_list_model_items_changed (G_LIST_MODEL (self),
|
||||
gtk_bitset_get_size_in_range (self->matches, 0, position),
|
||||
position > 0 ? gtk_bitset_get_size_in_range (self->matches, 0, position - 1) : 0,
|
||||
filter_removed, filter_added);
|
||||
}
|
||||
|
||||
@@ -337,10 +338,6 @@ gtk_filter_list_model_set_property (GObject *object,
|
||||
gtk_filter_list_model_set_incremental (self, g_value_get_boolean (value));
|
||||
break;
|
||||
|
||||
case PROP_ITEM_TYPE:
|
||||
self->item_type = g_value_get_gtype (value);
|
||||
break;
|
||||
|
||||
case PROP_MODEL:
|
||||
gtk_filter_list_model_set_model (self, g_value_get_object (value));
|
||||
break;
|
||||
@@ -369,10 +366,6 @@ gtk_filter_list_model_get_property (GObject *object,
|
||||
g_value_set_boolean (value, self->incremental);
|
||||
break;
|
||||
|
||||
case PROP_ITEM_TYPE:
|
||||
g_value_set_gtype (value, self->item_type);
|
||||
break;
|
||||
|
||||
case PROP_MODEL:
|
||||
g_value_set_object (value, self->model);
|
||||
break;
|
||||
@@ -582,22 +575,10 @@ gtk_filter_list_model_class_init (GtkFilterListModelClass *class)
|
||||
properties[PROP_INCREMENTAL] =
|
||||
g_param_spec_boolean ("incremental",
|
||||
P_("Incremental"),
|
||||
P_("Filer items incrementally"),
|
||||
P_("Filter items incrementally"),
|
||||
FALSE,
|
||||
GTK_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GtkFilterListModel:item-type:
|
||||
*
|
||||
* The #GType for elements of this object
|
||||
*/
|
||||
properties[PROP_ITEM_TYPE] =
|
||||
g_param_spec_gtype ("item-type",
|
||||
P_("Item type"),
|
||||
P_("The type of elements of this object"),
|
||||
G_TYPE_OBJECT,
|
||||
GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GtkFilterListModel:model:
|
||||
*
|
||||
@@ -608,7 +589,7 @@ gtk_filter_list_model_class_init (GtkFilterListModelClass *class)
|
||||
P_("Model"),
|
||||
P_("The model being filtered"),
|
||||
G_TYPE_LIST_MODEL,
|
||||
GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_EXPLICIT_NOTIFY);
|
||||
GTK_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GtkFilterListModel:pending:
|
||||
@@ -633,7 +614,7 @@ gtk_filter_list_model_init (GtkFilterListModel *self)
|
||||
|
||||
/**
|
||||
* gtk_filter_list_model_new:
|
||||
* @model: the model to sort
|
||||
* @model: (allow-none): the model to sort
|
||||
* @filter: (allow-none): filter or %NULL to not filter items
|
||||
*
|
||||
* Creates a new #GtkFilterListModel that will filter @model using the given
|
||||
@@ -647,10 +628,10 @@ gtk_filter_list_model_new (GListModel *model,
|
||||
{
|
||||
GtkFilterListModel *result;
|
||||
|
||||
g_return_val_if_fail (G_IS_LIST_MODEL (model), NULL);
|
||||
g_return_val_if_fail (model == NULL || G_IS_LIST_MODEL (model), NULL);
|
||||
g_return_val_if_fail (filter == NULL || GTK_IS_FILTER (filter), NULL);
|
||||
|
||||
result = g_object_new (GTK_TYPE_FILTER_LIST_MODEL,
|
||||
"item-type", g_list_model_get_item_type (model),
|
||||
"model", model,
|
||||
"filter", filter,
|
||||
NULL);
|
||||
@@ -658,26 +639,6 @@ gtk_filter_list_model_new (GListModel *model,
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_filter_list_model_new_for_type:
|
||||
* @item_type: the type of the items that will be returned
|
||||
*
|
||||
* Creates a new empty filter list model set up to return items of type @item_type.
|
||||
* It is up to the application to set a proper filter and model to ensure
|
||||
* the item type is matches.
|
||||
*
|
||||
* Returns: a new #GtkFilterListModel
|
||||
**/
|
||||
GtkFilterListModel *
|
||||
gtk_filter_list_model_new_for_type (GType item_type)
|
||||
{
|
||||
g_return_val_if_fail (g_type_is_a (item_type, G_TYPE_OBJECT), NULL);
|
||||
|
||||
return g_object_new (GTK_TYPE_FILTER_LIST_MODEL,
|
||||
"item-type", item_type,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_filter_list_model_set_filter:
|
||||
* @self: a #GtkFilterListModel
|
||||
|
||||
@@ -39,8 +39,6 @@ G_DECLARE_FINAL_TYPE (GtkFilterListModel, gtk_filter_list_model, GTK, FILTER_LIS
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkFilterListModel * gtk_filter_list_model_new (GListModel *model,
|
||||
GtkFilter *filter);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkFilterListModel * gtk_filter_list_model_new_for_type (GType item_type);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_filter_list_model_set_filter (GtkFilterListModel *self,
|
||||
|
||||
@@ -40,7 +40,6 @@
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_ITEM_TYPE,
|
||||
PROP_MODEL,
|
||||
NUM_PROPERTIES
|
||||
};
|
||||
@@ -64,7 +63,6 @@ struct _GtkFlattenListModel
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
GType item_type;
|
||||
GListModel *model;
|
||||
GtkRbTree *items; /* NULL if model == NULL */
|
||||
};
|
||||
@@ -157,9 +155,7 @@ gtk_flatten_list_model_get_nth_model (GtkRbTree *tree,
|
||||
static GType
|
||||
gtk_flatten_list_model_get_item_type (GListModel *list)
|
||||
{
|
||||
GtkFlattenListModel *self = GTK_FLATTEN_LIST_MODEL (list);
|
||||
|
||||
return self->item_type;
|
||||
return G_TYPE_OBJECT;
|
||||
}
|
||||
|
||||
static guint
|
||||
@@ -299,7 +295,6 @@ gtk_flatten_list_model_add_items (GtkFlattenListModel *self,
|
||||
{
|
||||
node = gtk_rb_tree_insert_before (self->items, after);
|
||||
node->model = g_list_model_get_item (self->model, position + i);
|
||||
g_warn_if_fail (g_type_is_a (g_list_model_get_item_type (node->model), self->item_type));
|
||||
g_signal_connect (node->model,
|
||||
"items-changed",
|
||||
G_CALLBACK (gtk_flatten_list_model_items_changed_cb),
|
||||
@@ -321,10 +316,6 @@ gtk_flatten_list_model_set_property (GObject *object,
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_ITEM_TYPE:
|
||||
self->item_type = g_value_get_gtype (value);
|
||||
break;
|
||||
|
||||
case PROP_MODEL:
|
||||
gtk_flatten_list_model_set_model (self, g_value_get_object (value));
|
||||
break;
|
||||
@@ -345,10 +336,6 @@ gtk_flatten_list_model_get_property (GObject *object,
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_ITEM_TYPE:
|
||||
g_value_set_gtype (value, self->item_type);
|
||||
break;
|
||||
|
||||
case PROP_MODEL:
|
||||
g_value_set_object (value, self->model);
|
||||
break;
|
||||
@@ -416,18 +403,6 @@ gtk_flatten_list_model_class_init (GtkFlattenListModelClass *class)
|
||||
gobject_class->get_property = gtk_flatten_list_model_get_property;
|
||||
gobject_class->dispose = gtk_flatten_list_model_dispose;
|
||||
|
||||
/**
|
||||
* GtkFlattenListModel:item-type:
|
||||
*
|
||||
* The #GType for elements of this object
|
||||
*/
|
||||
properties[PROP_ITEM_TYPE] =
|
||||
g_param_spec_gtype ("item-type",
|
||||
P_("Item type"),
|
||||
P_("The type of elements of this object"),
|
||||
G_TYPE_OBJECT,
|
||||
GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GtkFlattenListModel:model:
|
||||
*
|
||||
@@ -450,26 +425,20 @@ gtk_flatten_list_model_init (GtkFlattenListModel *self)
|
||||
|
||||
/**
|
||||
* gtk_flatten_list_model_new:
|
||||
* @item_type: The type of items in the to-be-flattened models
|
||||
* @model: (nullable) (transfer none): the item to be flattened
|
||||
* @model: (nullable) (transfer none): the model to be flattened
|
||||
*
|
||||
* Creates a new #GtkFlattenListModel that flattens @list. The
|
||||
* models returned by @model must conform to the given @item_type,
|
||||
* either by having an identical type or a subtype.
|
||||
* Creates a new #GtkFlattenListModel that flattens @list.
|
||||
*
|
||||
* Returns: a new #GtkFlattenListModel
|
||||
**/
|
||||
GtkFlattenListModel *
|
||||
gtk_flatten_list_model_new (GType item_type,
|
||||
GListModel *model)
|
||||
gtk_flatten_list_model_new (GListModel *model)
|
||||
{
|
||||
GtkFlattenListModel *result;
|
||||
|
||||
g_return_val_if_fail (g_type_is_a (item_type, G_TYPE_OBJECT), NULL);
|
||||
g_return_val_if_fail (model == NULL || G_IS_LIST_MODEL (model), NULL);
|
||||
|
||||
result = g_object_new (GTK_TYPE_FLATTEN_LIST_MODEL,
|
||||
"item-type", item_type,
|
||||
"model", model,
|
||||
NULL);
|
||||
|
||||
@@ -481,8 +450,7 @@ gtk_flatten_list_model_new (GType item_type,
|
||||
* @self: a #GtkFlattenListModel
|
||||
* @model: (nullable) (transfer none): the new model or %NULL
|
||||
*
|
||||
* Sets a new model to be flattened. The model must contain items of
|
||||
* #GListModel that conform to the item type of @self.
|
||||
* Sets a new model to be flattened.
|
||||
**/
|
||||
void
|
||||
gtk_flatten_list_model_set_model (GtkFlattenListModel *self,
|
||||
@@ -492,10 +460,6 @@ gtk_flatten_list_model_set_model (GtkFlattenListModel *self,
|
||||
|
||||
g_return_if_fail (GTK_IS_FLATTEN_LIST_MODEL (self));
|
||||
g_return_if_fail (model == NULL || G_IS_LIST_MODEL (model));
|
||||
if (model)
|
||||
{
|
||||
g_return_if_fail (g_type_is_a (g_list_model_get_item_type (model), G_TYPE_LIST_MODEL));
|
||||
}
|
||||
|
||||
if (self->model == model)
|
||||
return;
|
||||
|
||||
@@ -36,8 +36,7 @@ GDK_AVAILABLE_IN_ALL
|
||||
G_DECLARE_FINAL_TYPE (GtkFlattenListModel, gtk_flatten_list_model, GTK, FLATTEN_LIST_MODEL, GObject)
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkFlattenListModel * gtk_flatten_list_model_new (GType item_type,
|
||||
GListModel *model);
|
||||
GtkFlattenListModel * gtk_flatten_list_model_new (GListModel *model);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_flatten_list_model_set_model (GtkFlattenListModel *self,
|
||||
|
||||
@@ -784,7 +784,7 @@ update_fontlist (GtkFontChooserWidget *self)
|
||||
if ((self->level & GTK_FONT_CHOOSER_LEVEL_STYLE) == 0)
|
||||
model = g_object_ref (G_LIST_MODEL (fontmap));
|
||||
else
|
||||
model = G_LIST_MODEL (gtk_flatten_list_model_new (PANGO_TYPE_FONT_FACE, G_LIST_MODEL (fontmap)));
|
||||
model = G_LIST_MODEL (gtk_flatten_list_model_new (G_LIST_MODEL (fontmap)));
|
||||
gtk_filter_list_model_set_model (self->filter_model, model);
|
||||
g_object_unref (model);
|
||||
}
|
||||
|
||||
@@ -1,135 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2019 Benjamin Otte
|
||||
*
|
||||
* 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: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkfunctionslistitemfactory.h"
|
||||
|
||||
#include "gtklistitemfactoryprivate.h"
|
||||
#include "gtklistitemprivate.h"
|
||||
|
||||
struct _GtkFunctionsListItemFactory
|
||||
{
|
||||
GtkListItemFactory parent_instance;
|
||||
|
||||
GtkListItemSetupFunc setup_func;
|
||||
GtkListItemBindFunc bind_func;
|
||||
gpointer user_data;
|
||||
GDestroyNotify user_destroy;
|
||||
};
|
||||
|
||||
struct _GtkFunctionsListItemFactoryClass
|
||||
{
|
||||
GtkListItemFactoryClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GtkFunctionsListItemFactory, gtk_functions_list_item_factory, GTK_TYPE_LIST_ITEM_FACTORY)
|
||||
|
||||
static void
|
||||
gtk_functions_list_item_factory_setup (GtkListItemFactory *factory,
|
||||
GtkListItemWidget *widget,
|
||||
GtkListItem *list_item)
|
||||
{
|
||||
GtkFunctionsListItemFactory *self = GTK_FUNCTIONS_LIST_ITEM_FACTORY (factory);
|
||||
|
||||
if (self->setup_func)
|
||||
self->setup_func (list_item, self->user_data);
|
||||
|
||||
GTK_LIST_ITEM_FACTORY_CLASS (gtk_functions_list_item_factory_parent_class)->setup (factory, widget, list_item);
|
||||
|
||||
if (gtk_list_item_get_item (list_item) != NULL && self->bind_func)
|
||||
self->bind_func (list_item, self->user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_functions_list_item_factory_update (GtkListItemFactory *factory,
|
||||
GtkListItemWidget *widget,
|
||||
GtkListItem *list_item,
|
||||
guint position,
|
||||
gpointer item,
|
||||
gboolean selected)
|
||||
{
|
||||
GtkFunctionsListItemFactory *self = GTK_FUNCTIONS_LIST_ITEM_FACTORY (factory);
|
||||
|
||||
GTK_LIST_ITEM_FACTORY_CLASS (gtk_functions_list_item_factory_parent_class)->update (factory, widget, list_item, position, item, selected);
|
||||
|
||||
if (item != NULL && self->bind_func)
|
||||
self->bind_func (list_item, self->user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_functions_list_item_factory_finalize (GObject *object)
|
||||
{
|
||||
GtkFunctionsListItemFactory *self = GTK_FUNCTIONS_LIST_ITEM_FACTORY (object);
|
||||
|
||||
if (self->user_destroy)
|
||||
self->user_destroy (self->user_data);
|
||||
|
||||
G_OBJECT_CLASS (gtk_functions_list_item_factory_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_functions_list_item_factory_class_init (GtkFunctionsListItemFactoryClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkListItemFactoryClass *factory_class = GTK_LIST_ITEM_FACTORY_CLASS (klass);
|
||||
|
||||
object_class->finalize = gtk_functions_list_item_factory_finalize;
|
||||
|
||||
factory_class->setup = gtk_functions_list_item_factory_setup;
|
||||
factory_class->update = gtk_functions_list_item_factory_update;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_functions_list_item_factory_init (GtkFunctionsListItemFactory *self)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_functions_list_item_factory_new: (skip)
|
||||
* @setup_func: (scope call) (destroy user_destroy): the setup function for the list item factory
|
||||
* @bind_func: (scope call) (destroy user_destroy): the bind function for the list item factory
|
||||
* @user_data: user data for the @setup_func and @bind_func functions
|
||||
* @user_destroy: a function called to destroy @user_data
|
||||
*
|
||||
* Creates a new #GtkListItemFactory with the given functions.
|
||||
*
|
||||
* Returns: (transfer full): the newly created list item factory object
|
||||
*/
|
||||
GtkListItemFactory *
|
||||
gtk_functions_list_item_factory_new (GtkListItemSetupFunc setup_func,
|
||||
GtkListItemBindFunc bind_func,
|
||||
gpointer user_data,
|
||||
GDestroyNotify user_destroy)
|
||||
{
|
||||
GtkFunctionsListItemFactory *self;
|
||||
|
||||
g_return_val_if_fail (setup_func || bind_func, NULL);
|
||||
g_return_val_if_fail (user_data != NULL || user_destroy == NULL, NULL);
|
||||
|
||||
self = g_object_new (GTK_TYPE_FUNCTIONS_LIST_ITEM_FACTORY, NULL);
|
||||
|
||||
self->setup_func = setup_func;
|
||||
self->bind_func = bind_func;
|
||||
self->user_data = user_data;
|
||||
self->user_destroy = user_destroy;
|
||||
|
||||
return GTK_LIST_ITEM_FACTORY (self);
|
||||
}
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2019 Benjamin Otte
|
||||
*
|
||||
* 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: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __GTK_FUNCTIONS_LIST_ITEM_FACTORY_H__
|
||||
#define __GTK_FUNCTIONS_LIST_ITEM_FACTORY_H__
|
||||
|
||||
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gtk/gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gtk/gtklistitemfactory.h>
|
||||
#include <gtk/gtklistitem.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_FUNCTIONS_LIST_ITEM_FACTORY (gtk_functions_list_item_factory_get_type ())
|
||||
#define GTK_FUNCTIONS_LIST_ITEM_FACTORY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_FUNCTIONS_LIST_ITEM_FACTORY, GtkFunctionsListItemFactory))
|
||||
#define GTK_FUNCTIONS_LIST_ITEM_FACTORY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GTK_TYPE_FUNCTIONS_LIST_ITEM_FACTORY, GtkFunctionsListItemFactoryClass))
|
||||
#define GTK_IS_FUNCTIONS_LIST_ITEM_FACTORY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_FUNCTIONS_LIST_ITEM_FACTORY))
|
||||
#define GTK_IS_FUNCTIONS_LIST_ITEM_FACTORY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_TYPE_FUNCTIONS_LIST_ITEM_FACTORY))
|
||||
#define GTK_FUNCTIONS_LIST_ITEM_FACTORY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_FUNCTIONS_LIST_ITEM_FACTORY, GtkFunctionsListItemFactoryClass))
|
||||
|
||||
typedef struct _GtkFunctionsListItemFactory GtkFunctionsListItemFactory;
|
||||
typedef struct _GtkFunctionsListItemFactoryClass GtkFunctionsListItemFactoryClass;
|
||||
|
||||
/**
|
||||
* GtkListItemSetupFunc:
|
||||
* @item: the #GtkListItem to set up
|
||||
* @user_data: (closure): user data
|
||||
*
|
||||
* Called whenever a new list item needs to be setup for managing a row in
|
||||
* the list.
|
||||
*
|
||||
* At this point, the list item is not bound yet, so gtk_list_item_get_item()
|
||||
* will return %NULL.
|
||||
* The list item will later be bound to an item via the #GtkListItemBindFunc.
|
||||
*/
|
||||
typedef void (* GtkListItemSetupFunc) (GtkListItem *item, gpointer user_data);
|
||||
|
||||
/**
|
||||
* GtkListItemBindFunc:
|
||||
* @item: the #GtkListItem to bind
|
||||
* @user_data: (closure): user data
|
||||
*
|
||||
* Binds a#GtkListItem previously set up via a #GtkListItemSetupFunc to
|
||||
* an @item.
|
||||
*
|
||||
* Rebinding a @item to different @items is supported as well as
|
||||
* unbinding it by setting @item to %NULL.
|
||||
*/
|
||||
typedef void (* GtkListItemBindFunc) (GtkListItem *item,
|
||||
gpointer user_data);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gtk_functions_list_item_factory_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkListItemFactory * gtk_functions_list_item_factory_new (GtkListItemSetupFunc setup_func,
|
||||
GtkListItemBindFunc bind_func,
|
||||
gpointer user_data,
|
||||
GDestroyNotify user_destroy);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_FUNCTIONS_LIST_ITEM_FACTORY_H__ */
|
||||
@@ -1171,6 +1171,8 @@ gtk_grid_view_init (GtkGridView *self)
|
||||
gtk_list_base_set_anchor_max_widgets (GTK_LIST_BASE (self),
|
||||
self->max_columns * GTK_GRID_VIEW_MAX_VISIBLE_ROWS,
|
||||
self->max_columns);
|
||||
|
||||
gtk_widget_add_css_class (GTK_WIDGET (self), "view");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+3
-1
@@ -595,7 +595,7 @@ gtk_header_bar_class_init (GtkHeaderBarClass *class)
|
||||
g_param_spec_boolean ("show-title-buttons",
|
||||
P_("Show title buttons"),
|
||||
P_("Whether to show title buttons"),
|
||||
FALSE,
|
||||
TRUE,
|
||||
GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
@@ -629,6 +629,7 @@ gtk_header_bar_init (GtkHeaderBar *bar)
|
||||
|
||||
priv->title_widget = NULL;
|
||||
priv->decoration_layout = NULL;
|
||||
priv->show_title_buttons = TRUE;
|
||||
priv->state = GDK_SURFACE_STATE_WITHDRAWN;
|
||||
|
||||
priv->handle = gtk_window_handle_new ();
|
||||
@@ -646,6 +647,7 @@ gtk_header_bar_init (GtkHeaderBar *bar)
|
||||
gtk_center_box_set_end_widget (GTK_CENTER_BOX (priv->center_box), priv->end_box);
|
||||
|
||||
construct_title_label (bar);
|
||||
create_window_controls (bar);
|
||||
}
|
||||
|
||||
static GtkBuildableIface *parent_buildable_iface;
|
||||
|
||||
+7
-4
@@ -3573,12 +3573,15 @@ static void
|
||||
gtk_label_unrealize (GtkWidget *widget)
|
||||
{
|
||||
GtkLabel *self = GTK_LABEL (widget);
|
||||
GdkClipboard *clipboard;
|
||||
|
||||
clipboard = gtk_widget_get_primary_clipboard (widget);
|
||||
if (self->select_info &&
|
||||
gdk_clipboard_get_content (clipboard) == self->select_info->provider)
|
||||
gdk_clipboard_set_content (clipboard, NULL);
|
||||
self->select_info->provider)
|
||||
{
|
||||
GdkClipboard *clipboard = gtk_widget_get_primary_clipboard (widget);
|
||||
|
||||
if (gdk_clipboard_get_content (clipboard) == self->select_info->provider)
|
||||
gdk_clipboard_set_content (clipboard, NULL);
|
||||
}
|
||||
|
||||
GTK_WIDGET_CLASS (gtk_label_parent_class)->unrealize (widget);
|
||||
}
|
||||
|
||||
+13
-2
@@ -725,6 +725,8 @@ static const GtkBuildableParser offset_parser =
|
||||
offset_start_element
|
||||
};
|
||||
|
||||
static GtkBuildableIface *parent_buildable_iface;
|
||||
|
||||
static gboolean
|
||||
gtk_level_bar_buildable_custom_tag_start (GtkBuildable *buildable,
|
||||
GtkBuilder *builder,
|
||||
@@ -735,6 +737,10 @@ gtk_level_bar_buildable_custom_tag_start (GtkBuildable *buildable,
|
||||
{
|
||||
OffsetsParserData *data;
|
||||
|
||||
if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
|
||||
tagname, parser, parser_data))
|
||||
return TRUE;
|
||||
|
||||
if (child)
|
||||
return FALSE;
|
||||
|
||||
@@ -767,7 +773,11 @@ gtk_level_bar_buildable_custom_finished (GtkBuildable *buildable,
|
||||
self = data->self;
|
||||
|
||||
if (strcmp (tagname, "offsets") != 0)
|
||||
goto out;
|
||||
{
|
||||
parent_buildable_iface->custom_finished (buildable, builder, child,
|
||||
tagname, user_data);
|
||||
return;
|
||||
}
|
||||
|
||||
for (l = data->offsets; l != NULL; l = l->next)
|
||||
{
|
||||
@@ -775,7 +785,6 @@ gtk_level_bar_buildable_custom_finished (GtkBuildable *buildable,
|
||||
gtk_level_bar_add_offset_value (self, offset->name, offset->value);
|
||||
}
|
||||
|
||||
out:
|
||||
g_list_free_full (data->offsets, (GDestroyNotify) gtk_level_bar_offset_free);
|
||||
g_slice_free (OffsetsParserData, data);
|
||||
}
|
||||
@@ -783,6 +792,8 @@ gtk_level_bar_buildable_custom_finished (GtkBuildable *buildable,
|
||||
static void
|
||||
gtk_level_bar_buildable_init (GtkBuildableIface *iface)
|
||||
{
|
||||
parent_buildable_iface = g_type_interface_peek_parent (iface);
|
||||
|
||||
iface->custom_tag_start = gtk_level_bar_buildable_custom_tag_start;
|
||||
iface->custom_finished = gtk_level_bar_buildable_custom_finished;
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
* Because views do not display the whole list at once but only a few
|
||||
* items, they only need to maintain a few widgets at a time. They will
|
||||
* instruct the #GtkListItemFactory to create these widgets and bind them
|
||||
* to the items that are currently displayed.
|
||||
* to the items that are currently displayed.
|
||||
* As the list model changes or the user scrolls to the list, the items will
|
||||
* change and the view will instruct the factory to bind the widgets to those
|
||||
* new items.
|
||||
@@ -56,13 +56,13 @@
|
||||
* Various implementations of #GtkListItemFactory exist to allow you different
|
||||
* ways to provide those widgets. The most common implementations are
|
||||
* #GtkBuilderListItemFactory which takes a #GtkBuilder .ui file and then creates
|
||||
* and manages widgets everything automatically from the information in that file
|
||||
* widgets and manages everything automatically from the information in that file
|
||||
* and #GtkSignalListItemFactory which allows you to connect to signals with your
|
||||
* own code and retain full control over how the widgets are setup and managed.
|
||||
*
|
||||
* A #GtkListItemFactory is supposed to be final - that means its behavior should
|
||||
* not change and the first widget created from it should behave the same way as
|
||||
* the last widget created from it.
|
||||
* the last widget created from it.
|
||||
* If you intend to do changes to the behavior, it is recommended that you create
|
||||
* a new #GtkListItemFactory which will allow the views to recreate its widgets.
|
||||
*
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user