Compare commits

..

339 Commits

Author SHA1 Message Date
Matthias Clasen d080a2c482 gtk-demo: Plug memory leaks in the settings demo 2019-12-25 01:10:48 -05:00
Matthias Clasen 682dbe1c9c inspector: Use search instead of filtering for properties
This is mainly to test the search support.
2019-12-24 20:09:48 -05:00
Matthias Clasen 3f5d6bd8b5 listbase: search support
Add a filter to GtkListBase, and move the selection
to the first matching item whenever the filter changes.
This is meant to be used with single selection and
a string filter that is hooked up to a search entry.
2019-12-24 20:09:01 -05:00
Matthias Clasen 98aedb7592 inspector: Add columns to the object tree
Add columnview columns in the object tree.
We do the same for treeview columns.
2019-12-24 15:36:08 -05:00
Matthias Clasen b1fdd77ede builderlistitemfactory: Precompile the xml
This is the one place where we can really take advantage
of precompiling, since we instantiate this template
over and over.
2019-12-24 15:36:08 -05:00
Matthias Clasen ed7f507206 builder: Avoid a crash in error cases
Don't leave a dangling pointer behind. I've hit
cases where we crash trying to free it again.
2019-12-24 15:36:08 -05:00
Matthias Clasen a101e8079f builder: Avoid another critical
Only free an expression if we managed
to create one.
2019-12-24 15:36:08 -05:00
Matthias Clasen b8faadec64 builder: Avoid a critical
Check that the property exists before trying
to create a property expression, and report
an error if it doesn't.
2019-12-24 15:36:08 -05:00
Matthias Clasen 51b4768fd7 expression: Add a new property expression constructor
Allow creating property expresions from a GParamSpec.
This lets us avoid a critical, and instead report an
error in GtkBuilder if the property does not exist.
2019-12-24 15:36:08 -05:00
Matthias Clasen 8febf5e98a Spread single-click-activate api
This makes sense to have in all the views,
not just GtkListView.
2019-12-24 15:36:08 -05:00
Matthias Clasen 1d9e09aaca printdialog: Port to column view
This is not 100% complete. The search is not there yet.
2019-12-24 15:36:08 -05:00
Matthias Clasen eecb8092dc printer: Fix the default value of icon-name
Just set this to "printer", so we don't have
to fix it up in the print dialog.
2019-12-24 15:36:08 -05:00
Matthias Clasen ddd504ddfe printbackend: Add a list model getter
Now that we have a list model for printers,
we can start using it.
2019-12-24 15:36:08 -05:00
Matthias Clasen 4044a8cc6c printbackend: Use a list store 2019-12-24 15:36:08 -05:00
Matthias Clasen 05c869d19b inspector: Expand the actions list 2019-12-24 15:36:08 -05:00
Matthias Clasen 57d635e1a1 inspector: Expand the resource list
This is an experiment with adding a filler column.
2019-12-24 15:36:08 -05:00
Matthias Clasen 2c1a0d3d2e inspector: Expand the property list
It looks better this way.
2019-12-24 15:36:08 -05:00
Matthias Clasen d5d3b4b991 inspector: Expand the object tree
This is how it used to look, and it looks better that way.
2019-12-24 15:36:08 -05:00
Matthias Clasen 19166f15e3 columnview: Take expand into account
When allocating columns, distribute extra space
to columns that have expand set to TRUE.
2019-12-24 15:36:08 -05:00
Matthias Clasen fe31c2221c columnviewcolumn: Add an expand property
This will be used to determine how to distribute
available extra space in a column view.
2019-12-24 15:36:08 -05:00
Matthias Clasen 50e8ccf030 gtk-demo: Add more scrolling benchmarks
Add a listview and gridview to the scrolling
benchmarks.
2019-12-24 15:36:08 -05:00
Matthias Clasen 7539fe1acc gtk-demo: Make gridview demo use rubberbanding 2019-12-24 15:36:08 -05:00
Matthias Clasen ee03ae8b9b Add rubberband api
Add an enable-rubberband property to GtkListView,
GtkGridView and GtkColumnView.
2019-12-24 15:36:08 -05:00
Matthias Clasen 7bf21cf9d2 listbase: Add rubberband selection
Implement the typical rubberband selection, including
autoscroll. This is only useful with multiselection,
and not very compatible with single-click-activate.
Therefore, it is not enabled by default, and needs
to be turned on with the enable-rubber-band property.
2019-12-24 15:36:08 -05:00
Matthias Clasen 466aec41f5 multiselection: Add a copy constructor
Add a function to create a multiselection that
is a copy of an existing selection model. We
can do this efficiently if the original is a
multiselection as well, by just copying the
entire set in on go.
2019-12-24 15:36:08 -05:00
Matthias Clasen 5e9adeb9bf Add GtkMultiSelection
This is implemented using a private GtkSet helper.
2019-12-24 15:36:08 -05:00
Matthias Clasen c7b2307a0b columnviewtitle: Display a context menu
When the ::header-menu property is set on the
column, use the menu model to create and show
a context menu.
2019-12-24 15:36:08 -05:00
Matthias Clasen 6e838098cb columnviewcolumn: Add a menu property
Add a ::header-menu property that will be used
to create a context menu for the header of the
column.
2019-12-24 15:36:08 -05:00
Matthias Clasen ee76623e54 Add a selection model test
The test shows that we are failing to emit
::selection-changed in some circumstances.
2019-12-24 15:36:08 -05:00
Matthias Clasen 36aaece297 testcolumnview: Reordering in the column editor
Use Ctrl-Up/Down to move the column around.
2019-12-24 15:36:08 -05:00
Matthias Clasen 4c8de636ce testcolumnview: Flesh out column editor
Turn the column list into an editor with
controls for visibility, resizability, reorderability
and width.
2019-12-24 15:36:08 -05:00
Matthias Clasen 8c086dbdc7 columview: Add autoscroll
Autoscroll when the pointer gets close to the
edge during column resizing or reordering. This
is similar to what the treeview does, but it is
implemented using a tick callback, and has
variable speed.
2019-12-24 15:36:08 -05:00
Matthias Clasen f86aeaf8cd columnview: Allow to cancel reorder with Escape
The treeview does this too.
2019-12-24 15:36:08 -05:00
Matthias Clasen c814864a3f columnview: Interactive column reordering
Allow rearranging columns by dragging, in the same
way the treeview does.

We add the "dnd" style class to the header while
it is dragged, and we move the header of the dragged
column to the end of its parents children, so that
it gets drawn on top.
2019-12-24 15:36:08 -05:00
Matthias Clasen 9e9d4d914e columnviewcolumn: Add a reorderable property
This will be used for interactive column reordering
in the future.
2019-12-24 15:36:08 -05:00
Matthias Clasen 8f2351d5d3 columnviewlayout: Use header allocation for titles
Normally, this will be identical to the column
allocation, but we will temporarily change it
during column reordering.
2019-12-24 15:36:08 -05:00
Matthias Clasen 4817c7757b columnviewcolumn: Add reordering helpers
Add helper functions that let us temporarily give
a different allocation to headers. These will be
used to implement interactive column reordering
in GtkColumnView.
2019-12-24 15:36:08 -05:00
Matthias Clasen a44c4b4877 columnviewtitle: Invert on release
This is necessary to make drag-to-reorder work
without triggering inversion.
2019-12-24 15:36:08 -05:00
Matthias Clasen f8a14427ea columnview: Interactive column resizing
This copies just enough of the treeview code to
get columns moving.
2019-12-24 15:36:08 -05:00
Matthias Clasen 9d0904a445 columnviewcolumn: Add a helper
We need to check whether clicks are in the headers
of columns, so let the column view get at the the
header widget.
2019-12-24 15:36:08 -05:00
Matthias Clasen 4a659c169d columnviewcolumn: Add a resizable property
This will be used for interactive column resizing
in the future.
2019-12-24 15:36:08 -05:00
Matthias Clasen 5ca53555c7 Turn GtkRecentInfo into an object
This is in preparation to eventually using
a list model of recent infos.
2019-12-24 15:36:08 -05:00
Matthias Clasen 0bbc074e08 gtk-demo: Add row reordering to the settings demo 2019-12-24 15:36:08 -05:00
Matthias Clasen 7af244944a gtk-demo: Add filtering to the settings demo
A demo of filtering with lists was missing so far.
2019-12-24 15:36:08 -05:00
Matthias Clasen ae084d2929 gtk-demo: Crank up max columns of gridview
This lets us fit more cells on screen.
2019-12-24 15:36:08 -05:00
Matthias Clasen fe3dd5cd8b gtk-demo: Make gridview content switchable
Add a dropdown to switch out the item factory.
2019-12-24 15:36:08 -05:00
Matthias Clasen 3dbac6b133 gtk-demo: Add sorting to the gridview demo 2019-12-24 15:36:08 -05:00
Matthias Clasen 2cb5ce8c72 gtk-demo: Cosmetic changes for the flowbox demo
Mention the size of the dataset.
2019-12-24 15:36:08 -05:00
Matthias Clasen 8ae6e58e0c gtk-demo: Cosmetic changes to the file browser demo
Mention that it involves switching between
different views.
2019-12-24 15:36:08 -05:00
Matthias Clasen 6eebc9183a gtk-demo: Cosmetic changes for the weather demo
Give the weather demo a size and a title, and mention
the size of the dataset in the description.
2019-12-24 15:36:08 -05:00
Matthias Clasen b84780cc98 gtk-demo: Cosmetic changes to the clocks demo
Give the clocks demo a title and size,
and tweak the description.
2019-12-24 15:36:08 -05:00
Matthias Clasen 46a6ab68f2 gtk-demo: Demo columnview sorting
Enhance the settings demo to have a sortable column.
2019-12-24 15:36:08 -05:00
Matthias Clasen e5c57d10d7 filechooser: Use a dropdown for choices 2019-12-24 15:36:08 -05:00
Matthias Clasen 9aed6a2b56 filechooser: Use a dropdown for the filter combo 2019-12-24 15:36:08 -05:00
Matthias Clasen 843fa70bef inspector: Use dropdowns in the visual page
Convert everything in the visual page to dropdowns.
2019-12-24 15:36:08 -05:00
Matthias Clasen 2ea918a5e7 inspector: Use a dropdown for size groups
Use a GtkDropDown for the modes of size groups.
2019-12-24 15:36:08 -05:00
Matthias Clasen f7608a2119 inspector: Use a dropdown for controllers
Use a GtkDropDown for the phases of event controllers.
2019-12-24 15:36:07 -05:00
Matthias Clasen f55528fd10 inspector: Use a dropdown for attribute mapping
Use a GtkDropDown for the attribute mapping editor.
2019-12-24 15:36:07 -05:00
Matthias Clasen 1d7322ed63 inspector: Use dropdowns in property editor
Replace combo boxes by dropdowns in the property editor.
2019-12-24 15:36:07 -05:00
Matthias Clasen f3dc528e7d Add GtkDropDown
This is a simple drop down control using list models.
2019-12-24 15:36:07 -05:00
Matthias Clasen 6265a60663 columnview: Add a helper
The column code needs to get access to the
listitem widgets that are children of the listview,
so add a getter.
2019-12-24 15:36:07 -05:00
Matthias Clasen 08bbf44602 columnview: Add column reordering
Add an API to allow reordering columns.
2019-12-24 15:36:07 -05:00
Matthias Clasen 640f165a81 columnviewcolumn: Add a fixed-width property
When fixed-width is set to a value > -1, we make the
measure function of cell and title widgets return this
width, and we set overflow to hidden.
2019-12-24 15:36:07 -05:00
Matthias Clasen 34cbaa9057 columnview: Implement horizontal scrolling
The listview inside always thinks it gets its full size,
and updates its horizontal adjustment accordingly.

So keep our own adjustment, and update it in size_allocate.
2019-12-24 15:36:07 -05:00
Matthias Clasen 2f666332ea columnview: Revise scroll-minimum handling
Tweak the behavior slightly. We don't show
a scrollbar as long as we have at least
min-size available, but we still give the
entire size to the child, up to nat-size.

This matches how viewports handle scroll-minimum.
2019-12-24 15:36:07 -05:00
Matthias Clasen 972090f34d column: Add a visible property
This lets us hide columns, which is useful.
2019-12-24 15:36:07 -05:00
Matthias Clasen 6ab8b1cfe5 inspector: Touch up list styling
This is just the minimal amount of work to make
headers recognizable.
2019-12-24 15:36:07 -05:00
Matthias Clasen 84fd2290a6 inspector: Use a column view for actions
A straight conversion from list box to column view.
2019-12-24 15:36:07 -05:00
Matthias Clasen 55f9e86d67 inspector: Make the resource list sortable
This is using a GtkTreeListRowSorter to keep expanded
state of the tree while changing the sorting.
2019-12-24 15:36:07 -05:00
Matthias Clasen 9892831d52 inspector: Use a column view for the resource list
A conversion from tree view to column view.
2019-12-24 15:36:07 -05:00
Matthias Clasen baff649ca6 inspector: Use a column view for properties
Just a straight conversion from list box to column view.
2019-12-24 15:36:07 -05:00
Matthias Clasen 921ff0460b columnview: Add a sort-by api 2019-12-24 15:36:07 -05:00
Matthias Clasen cab09d27db columnview: Document sorting
Add a paragraph outlining how sorting is set up
for GtkColumnView.
2019-12-24 15:36:07 -05:00
Matthias Clasen 65b3a9358a docs: Fix misc typos and omissions 2019-12-24 15:36:07 -05:00
Matthias Clasen 649bcc69e3 docs: Add more private headers to ignore 2019-12-24 15:36:07 -05:00
Matthias Clasen 2357771bd9 treelistmodel: Small documentation tweaks 2019-12-24 15:36:07 -05:00
Matthias Clasen d53a0ba584 sorter: Small documentation fixes 2019-12-24 15:36:07 -05:00
Matthias Clasen e2f78e95b2 numericsorter: Small documentation improvements 2019-12-24 15:36:07 -05:00
Matthias Clasen dea3c8aed0 multisorter: Small documntation improvements 2019-12-24 15:36:07 -05:00
Matthias Clasen f2a82e7d35 multifilter: Small documentation improvements 2019-12-24 15:36:07 -05:00
Matthias Clasen 9ff85899d0 builderlistitemfactory: Add an example to the docs 2019-12-24 15:36:07 -05:00
Matthias Clasen 602d141a7b maplistmodel: Add an example to the docs 2019-12-24 15:36:07 -05:00
Matthias Clasen 0bed5a8b9d stringfilter: Documnentation additions 2019-12-24 15:36:07 -05:00
Matthias Clasen f2a50fa590 filter: Documentation fixes 2019-12-24 15:36:07 -05:00
Matthias Clasen f833959acd filterlistmodel: Documentation fixes 2019-12-24 15:36:07 -05:00
Matthias Clasen 02168260e0 expression: Small documentation fixes 2019-12-24 15:36:07 -05:00
Matthias Clasen 68fbb59f82 docs: Add gtk_expression_watch_unwatch 2019-12-24 15:36:07 -05:00
Matthias Clasen e7f3a4f61a expression: Correct an example in the docs 2019-12-24 15:36:07 -05:00
Matthias Clasen e32ae895e3 Add some tests for new GtkBuilder syntax
Some valid and invalid examples for <closure>,
<lookup> and <constant>.
2019-12-24 15:36:07 -05:00
Matthias Clasen 44c5d47ed8 gtk-builder-tool: Minimally validate <binding>
Check that the toplevel property name is legit.
2019-12-24 15:36:07 -05:00
Matthias Clasen a9f963b5d9 multifilter: Fix a few annotations 2019-12-24 15:36:07 -05:00
Matthias Clasen 0a711ec0b2 builderlistitemfactory: Fix a few annotations 2019-12-24 15:36:07 -05:00
Matthias Clasen 1630482d13 treelistrowsorter: Fix a doc typo 2019-12-24 15:36:07 -05:00
Matthias Clasen bdaa41184f columnviewcolumn: Fix a type mismatch
The column-view property was declared with the wrong
type. This was causing criticals in the inspector.
2019-12-24 15:36:07 -05:00
Matthias Clasen 0a36ba0611 listitemwidget: Fix single-click-activate
This was broken by the renaming of ::contains-pointer-focus
to ::contains-pointer. Fix it up.
2019-12-24 15:36:07 -05:00
Matthias Clasen cc39cc2e8d Fix gtk_column_view_create_cells
This code was assuming that the listitem widgets
are children of the column view, which they aren't.
2019-12-24 15:36:07 -05:00
Matthias Clasen 51e2a51dfd filterlistmodel: Remove pre-filter remnants
We are not using the filter func typdef anymore.
2019-12-24 15:36:07 -05:00
Matthias Clasen 90b32cac0b Add filter test to testsuite 2019-12-22 23:12:21 -05:00
Matthias Clasen b56cfc5293 Add a test for multi filter unreffing
This tests the fix in the previous commit.
2019-12-22 23:12:21 -05:00
Matthias Clasen 7bb1f036d6 multifilter: Remove an extraneous unref
The sequence is using unref as free func,
no need to ido it ourselves.
2019-12-22 23:12:21 -05:00
Benjamin Otte 0cd203b07d testsuite: Add tests for GtkTreeListSorter 2019-12-18 05:48:03 +01:00
Matthias Clasen 86b29d4d7a Add GtkTreeListRowSorter
This is a special-purpose sorter that can
apply the sorting of another sorter to the
levels of a GtkTreeListModel.
2019-12-18 05:48:02 +01:00
Benjamin Otte 3ffb005135 testcolumnview: Add sorters 2019-12-18 05:48:02 +01:00
Matthias Clasen a4b15d205e column view title: Show sort indicators 2019-12-18 05:48:02 +01:00
Matthias Clasen 0b4f75cf25 columnview: Add sorting
This is a somewhat large commit that:

- Adds GtkColumnViewSorter
This is a special-purpose, private sorter implementation which sorts
according to multiple sorters, allowing each individual sorter to be
inverted. This will be used with clickable column view headers.

- Adds a read-only GtkColumnView::sorter property
The GtkColumnView creates a GtkColumnViewSorter at startup that it uses
for this property.

- Adds a writable GtkColumnViewColumn::sorter property
This allows defining per-column sorters. Whenever an application sets a
sorter for a column, the header becomes clickable and whenever
a header is clicked, that column's sorter is prepended to the list of
sorters, unless it is already the first sorter, in which case we invert
its order. No column can be in the list more than once.
2019-12-18 05:48:02 +01:00
Matthias Clasen 163477acfb gtk-demo: Add a large grid demo
This is similar to the flowbox demo, but much bigger.
2019-12-18 05:45:39 +01:00
Matthias Clasen f80335505e listview: Add single-click-activate
Add a single-click-activate property to GtkListView.
2019-12-18 05:45:39 +01:00
Matthias Clasen ffdcde53f5 listitemwidget: Add single-click-activate
Add a mode to GtkListItemWidget that activates on
single click and selects on hover. Make
GtkListItemManager set this on its items
when its own 'property' of the same name is set.
2019-12-18 05:45:39 +01:00
Matthias Clasen 5d836b5e15 builder-tool: Pass through CDATA where it makes sense
This avoids a ton of escaping for
GtkBuilderListItemFactory::bytes.
2019-12-18 05:45:39 +01:00
Matthias Clasen 539213133f docs: Reorganize list widgets in their own chapter 2019-12-18 05:45:39 +01:00
Benjamin Otte 6977a03f65 fontchooserwidget: Port to listmodels
The port is kind of evil, in that it stores either a PangoFontFamily or a
PangoFontFace in the list, depending on if the fontchooser is configured
to select fonts or faces.
It also does not cache the font description anymore, so more calls to
pango_font_describe() may happen.

If both of these issues turn out problematic, the fontchooser would need
to resurrect GtkDelayedFontDescription again and put objects of that
type through the model.

These changes depend on Pango 1.46's introduction of listmodels and
various new getters, so the dependency has been upgraded.
2019-12-18 05:45:39 +01:00
Matthias Clasen 0875374b1d Add some tests for expression binding
In particular, test that expressios can deal with object == this.
2019-12-18 05:45:39 +01:00
Benjamin Otte fe1ce2aaf8 expression: Allow passing a this object to bind()
This gives a bit more control over the arguments passed to expressions.
2019-12-18 05:45:39 +01:00
Benjamin Otte a81429c10f widget: Do parent_class handling properly
The previous cosde did not actually query the parent class, it just did
a very complicated C cast.
2019-12-18 05:45:39 +01:00
Benjamin Otte 2f52d98ef4 gtk-demo: Add a Clocks demo
This demo is meant to showcase expressions.

It also needs the fixes in glib 2.64 to work properly.
2019-12-18 05:45:39 +01:00
Benjamin Otte 5a076b0c2f xxx: Add a hack to make paintables transform to/from objects
See also: https://gitlab.gnome.org/GNOME/glib/merge_requests/1251
2019-12-18 05:45:39 +01:00
Benjamin Otte 69f59109ee inspector: Remove private struct for prop editor 2019-12-18 05:45:39 +01:00
Benjamin Otte 6bf508ce73 inspector: Make Controller page a GtkWidget 2019-12-18 05:45:39 +01:00
Benjamin Otte ae26ce017b inspector: Remove private struct from controllers 2019-12-18 05:45:39 +01:00
Benjamin Otte 0a126f65fb columnview: Add header
This uses a custom GtkColumnViewTitle widget. So far that widget is
pretty boring, but that will change once we added
resizing, reordering, dnd, sorting, hiding/showing of columns or
whatever UIs we want.
2019-12-18 05:45:39 +01:00
Benjamin Otte 6d0695260d tests: Add testcolumnview 2019-12-18 05:45:37 +01:00
Benjamin Otte a43e0b1e62 columnview: Add a custom LayoutManager
The ColumnView now allocates column widths first and then the individual
rows use the new layout manager which looks at the column allocations to
allocate their children.
2019-12-15 23:33:04 +01:00
Benjamin Otte 01d4a28c9f constraint-editor: Don't poke around in widget internals 2019-12-15 23:33:04 +01:00
Benjamin Otte 052343ca7d columnview: Fix styling with Adwaita
- Use "treeview" as the node name
- Add .view style class
2019-12-15 23:33:04 +01:00
Benjamin Otte 7f4260f97e inspector: Port object tree to GtkColumnView 2019-12-15 23:33:04 +01:00
Benjamin Otte 2b42f0fcb3 columnview: Add GtkColumnViewCell
It's a GtkListItemWidget subclass that tracks the column it belongs to
and allows the column to track it.

We also use this subclass to implement sizing support so columns share
the same size and get resized in sync.
2019-12-15 23:33:04 +01:00
Benjamin Otte f46c405351 widget: Add a hook for resizes
It's private, no APIs, we don't talk about it. But we will start using
it very soon, so we can do size request caching in columns and avoid
sizegroups...
2019-12-15 23:33:04 +01:00
Benjamin Otte 8f4a0391b3 columnview: Implement GtkScrollable
Just forward it to the listview for now.
2019-12-15 23:33:04 +01:00
Benjamin Otte 5b282411c4 columnview: Add listitems for the columns
They are not aligned in columns yet, but they do exist.
2019-12-15 23:33:04 +01:00
Benjamin Otte e4392bdf5a listitemwidget: Lazily create listitems
We only create them in root/unroot (they should be created in
appear/disappear, but that vfunc doesn't exist yet), that way we can
avoid expensive work while the widget isn't used for anything.
2019-12-15 23:33:04 +01:00
Benjamin Otte e845e93f58 listitem: Move position/item/selected tracking to widget
This way, we can ensure it's always there when we need it (before the
item gets created) and gone when we don't (if some GC language holds on
to the item after we've destroyed the widget).
2019-12-15 23:33:04 +01:00
Benjamin Otte 98b4269abd listitemwidget: Add a private struct
I had to rename the item property to list_item anyway, so I could just
do the next step with it.
2019-12-15 23:33:04 +01:00
Benjamin Otte 9b132b80ae listitemfactory: Simplify
Instead of 6 vfuncs, we now have 3 and rely on the factory keeping track
of what it needs to do.

We're doing lots of dancing from one object to another here, but this
will hopefully get simpler with further commits.
2019-12-15 23:33:04 +01:00
Benjamin Otte 7c402bcf2c listitemfactory: Reorganize vfuncs
Instead of bind/rebind/update/unbind, we now just have update, and the
factories get to interpret that in the way they want.
2019-12-15 23:33:04 +01:00
Benjamin Otte 6d73e3a6fa listitem: Make this a GObject
This splits GtkListItem into 2 parts:

1. GtkListItem
   This is purely a GObject with public API for developers who want to
   populate lists. There is no chance to cause conflict with GtkWidget
   properties that the list implementation assumed control over and
   defines a clear boundary.
2. GtkListItemWidget
   The widget part of the listitem. This is not only fully in control of
   the list machinery, the machinery can also use different widget
   implementations for different list widgets like I inted to for
   GtkColumnView.
2019-12-15 23:33:04 +01:00
Benjamin Otte 730575677f builder: Make gtk_builder_extend_with_template() work with objects
This will be relevant later when we introduce GtkListItem which is not a
GtkWidget.
2019-12-15 23:33:04 +01:00
Benjamin Otte d4d07bcb2a gtk-demo: Add a Coverflow application launcher
This is roughly the simplest demo I could come up with.

But I documented it, so there's your tutorial.

Related: #2214
2019-12-15 23:33:04 +01:00
Benjamin Otte 01cdc67db0 Add GtkSignalListItemFactory
So the poor Rust users can actually use this.

I would totally not use this ever!
2019-12-15 23:33:04 +01:00
Benjamin Otte 77c9d0d0fb columnview: Allow adding/removing columns
... and make that work in UI files via <child>, too.
2019-12-15 23:33:04 +01:00
Benjamin Otte 3cc9fa9f67 gtk-demo: Add a minesweeper demo
The demo shows creating ones own listmodel and using it to fill a grid.

I am totally getting the hang of React btw:
500 lines of logic with no UI code and 100 lines of GtkBuilder XML and
I get a sweet UI.
2019-12-15 23:33:04 +01:00
Benjamin Otte 181b9655ef Add GtkColumnView skeleton
It's just a copy/paste of the listview code with all the internals
gutted. The code doesn't do anything.
2019-12-15 23:33:04 +01:00
Benjamin Otte 1eab9ba350 wip: Add GtkCoverFlow
The widget mostly works out of the box, but some tweaking may be
necessary (in particular in the theme) and the gtk-demo changes might
require removing before this is production-ready.
2019-12-15 23:33:04 +01:00
Benjamin Otte d1d0adeae9 listbase: Take over anchor handling
With that, pretty much all code but allocating the widgets is gone from
the gridview and listview.
2019-12-15 23:33:04 +01:00
Benjamin Otte 64a2f04006 listbase: Add vfuncs to convert positions to/from coordinates
... and use that to implement PageUp/PageDown.

With that, all keyboard handling has been moved to GtkListBase.
2019-12-15 23:33:04 +01:00
Benjamin Otte c835bb30d1 listbase: Move focus moving keybindings here
The focus tracker is not yet moved because that depends on scroll_to()
support and we don't have that yet.
Whoops.
So we use a hack.
2019-12-15 23:33:04 +01:00
Benjamin Otte 96d333f649 Remove gtk_selection_model_user_select_item() again
This reverts commit 6a164ab306dad9096bde736c907494c71086d3c4.

The function was awkward and we now have only one caller again, so we
can fold it back into it.
2019-12-15 23:33:04 +01:00
Benjamin Otte 66142ae74f listbase: Move orientable implementation here 2019-12-15 23:33:04 +01:00
Benjamin Otte 75f539b3a4 listbase: Move selection handling here 2019-12-15 23:33:04 +01:00
Benjamin Otte ad12914c55 listbase: Move item manager here
Nothing really changes, because both ListView and GridView still keep
self->item_manager around, but it's set up to point at the base's item
manager.

This way we can slowly move things to GtkListBase that need the item
manager (like trackers).
2019-12-15 23:33:04 +01:00
Benjamin Otte f614011569 listbase: Move GtkScrollable implementation
Shared code between GtkGridView and GtkListView.
2019-12-15 23:33:04 +01:00
Benjamin Otte 013db26d22 Add GtkListBase
This is a base item for GTK's list widgets so they can share some (read:
hopefully a lot of) code.
2019-12-15 23:33:04 +01:00
Benjamin Otte 9fab1b3d25 gridview: Simplify allocation code
It doesn't fix the bug I'm after, but it looks a lot better.
2019-12-15 23:33:04 +01:00
Benjamin Otte c3bb95d7d9 listview: Port various gridview improvements
- Handle anchor as align + top/bottom
  This fixes behavior for cells that are higher than the view
- Add gtk_list_view_adjustment_is_flipped()
  This should fix RTL handling of horizontal lists
- Fix scrolling
  This should make scrolling more reliable, particularly on short lists
  that are only a few pages long.
2019-12-15 23:33:04 +01:00
Benjamin Otte 27a891adb8 demo: Add a file browser demo 2019-12-15 23:33:04 +01:00
Benjamin Otte 94b162829c gridview: Add move keybindings 2019-12-15 23:33:04 +01:00
Benjamin Otte e54f3f68a0 gridview: Implement (un)select all
Adds listitem.select-all and listitem.unselect-all actions and installs
the same keybindings as the treeview for those actions.
2019-12-15 23:33:04 +01:00
Benjamin Otte ddc665bb01 gridview: Add a focus tracker
... and use that to properly update selections when moving around with
the arrow keys.
2019-12-15 23:33:04 +01:00
Benjamin Otte d0495e36e6 gridview: Implement list.scroll-to action 2019-12-15 23:33:04 +01:00
Benjamin Otte 4444bb3d98 gridview: Add activation 2019-12-15 23:33:04 +01:00
Benjamin Otte b9616124cb gridview: Implement minimum row height
We only allocate a certain amount of widgets - and we don't want to run
out of them. So we make all widgets high enough for this to never
happen.
2019-12-15 23:33:04 +01:00
Benjamin Otte 6218a27daf gridview: Implement the list.select-item action 2019-12-15 23:33:04 +01:00
Benjamin Otte 51ecc2d566 selectionmodel: Add gtk_selection_model_user_select_item()
I'm not sure this should be public API because it's incredibly awkward.
But it should definitely be shared between list widget implementations.
2019-12-15 23:33:04 +01:00
Benjamin Otte 050bd6d5e3 gridview: Implement anchors and scrolling 2019-12-15 23:33:04 +01:00
Benjamin Otte 0229f11784 widget: Add gtk_widget_get_size()
A little bit of convenience.
2019-12-15 23:33:04 +01:00
Benjamin Otte cee950b455 listitemmanager: Handle NULL factory
Just don't call it and create empty listitems.
2019-12-15 23:33:04 +01:00
Timm Bäder 3a5f47c3b8 demo: Use a listview as sidebar 2019-12-15 23:33:04 +01:00
Benjamin Otte 484f804ba6 gtk-demo: Introduce awards
We need a way to get a useful listbox, so here we go!
2019-12-15 23:33:04 +01:00
Benjamin Otte 5b96335956 builder: Autofill scope property of listitemfactory
I couldn't come up with a better way to automatically inherit the scope
in the builder list item factory that didn't involve a magic
incantation in the XML file. And I do not want developers to know magic
incantations to do a thing that should pretty much always be done.
2019-12-15 23:33:04 +01:00
Benjamin Otte 61362af27b builderlistitemfactory: Add scope argument
This way, the scope used when creating builder instances can be
influenced. This way, callbacks can be passed into the factory.
2019-12-15 23:33:04 +01:00
Benjamin Otte fc82f5fe29 listitemfactory: Make the builder factory properly buildable
Turn the construct arguments into construct properties so that they can
be set from ui files.
2019-12-15 23:33:04 +01:00
Benjamin Otte 5ae2c1fdca listview: Add move keybindings
My god, these are a lot.

And my god, these are complicated to get right.
2019-12-15 23:33:04 +01:00
Benjamin Otte eba9ec613d listview: Add gtk_list_view_get_position_at_y() 2019-12-15 23:33:04 +01:00
Benjamin Otte 61fc0a6a59 listitem: Add "listitem.select" action and keybindings for it
In fact, grab space with all modifiers to toggle selection of the
current item.
2019-12-15 23:33:03 +01:00
Benjamin Otte 250760468b listview: Add a focus tracker
This ensures that the row with the input focus always stays available,
even when scrolled out of view.
2019-12-15 23:33:03 +01:00
Benjamin Otte 9d5063cf68 listview: Implement (un)select all
Adds listitem.select-all and listitem.unselect-all actions and installs
the same keybindings as the treeview for those actions.
2019-12-15 23:33:03 +01:00
Benjamin Otte c4af364bfb listview: Track focus movements and update selection
When focus moves via tab/arrow, we need to select the new item.
2019-12-15 23:33:03 +01:00
Benjamin Otte 3e1cad5755 listview: Implement activation
- a GtkListview::activate signal
- a GtkListItem::activatable property
- activate list items on double clicks and <Enter> presses
2019-12-15 23:33:03 +01:00
Benjamin Otte 42c077443e treeexpander: Implement input support
This implements all the keybindings from GtkTreeView that can be
supported.

It does not implement expand-all, because supporting that means
causing the TreeListModel to emit lots of create_model vfuncs which in
turn would cause many items-changed signal which in turn would cause
many signal handlers to run which in turn would make "expand-all" very
reentrant, and I'm uneasy about supporting that.

For the mouse, just add a click gesture to the expander icon that toggles
expanded state.
2019-12-15 23:33:03 +01:00
Benjamin Otte 7a49d2e848 listitem: Change focus handling
Focus in the listitem now works like this:
1. If any child can take focus, do not ever attempt
   to take focus.
2. Otherwise, if this item is selectable or activatable,
   allow focusing this widget.

This makes sure every item in a list is focusable for
activation and selection handling, but no useless widgets
get focused and moving focus is as fast as possible.
2019-12-15 23:33:03 +01:00
Benjamin Otte 462953cac0 inspector: Make the recorder node list use a ListView
It's quite a bit faster now, but the code is also a bit more awkward.

Pain points:

- GtkTreeListModel cannot be created in UI files because it needs
  a CreateModelFunc.
  Using a signal for this doesn't work because autoexpand wants to
  expand the model before the signal handler is connected.

- The list item factory usage is still awkward. It's bearable here
  because the list items are very simple, but still.
2019-12-15 23:33:03 +01:00
Benjamin Otte 5b5ab5c592 inspector: Use a GtkTreeExpander in the object tree 2019-12-15 23:33:03 +01:00
Benjamin Otte d89f9b6684 inspector: Use a treeexpander in the recorder 2019-12-15 23:33:03 +01:00
Benjamin Otte 71f104782a demo: Add a GSettings tree demo
It is meant to look somewhat like dconf-editor when it is done.

So far, it's just a list.
2019-12-15 23:33:03 +01:00
Benjamin Otte 297a2795c3 Add GtkTreeExpander
This is a container widget that takes over all the duties of tree
expanding and collapsing.
It has to be a container so it can capture keybindings while focus is
inside the listitem.

So far, this widget does not allow interacting with it, but it shows the
expander arrow in its correct state.

Also, testlistview uses this widget now instead of implementing
expanding itself.
2019-12-15 23:33:03 +01:00
Benjamin Otte 081645186d gridview: Actually do something
Implement measuring and allocating items - which makes the items appear
when drawing and allows interacting with the items.

However, the gridview still does not allow any user interaction
(including scrolling).
2019-12-15 23:33:03 +01:00
Benjamin Otte 20201662f1 listview: Pass the CSS name of listitems to the manager
... instead of hardcoding "row".
2019-12-15 21:11:03 +01:00
Benjamin Otte 3c97226e66 gridview: Implement GtkOrientable
Again, this is just the skeleton, because the Gridview does nothing yet.
2019-12-15 21:11:03 +01:00
Benjamin Otte 6b4b1e1921 gridview: Add factory handling
Just copy the listview APIs.

Code still doesn't do anything with it.
2019-12-15 21:11:03 +01:00
Benjamin Otte 246421f92c listview: Expose GtkListItemFactory APIs
Due to the many different ways to set factories, it makes sense to
expose them as custom objects.

This makes the actual APIs for the list widgets simpler, because they
can just have a regular "factory" property.

As a convenience function, gtk_list_view_new_with_factory() was added
to make this whole approach easy to use from C.
2019-12-15 21:11:03 +01:00
Benjamin Otte 603055b70d textview: Make cursor work when blinking is disabled 2019-12-15 21:10:29 +01:00
Benjamin Otte 6a26bb0e2f gtk-demo: Add a rough start at a Weather demo
This demos a horizontal listview.
2019-12-15 21:10:29 +01:00
Benjamin Otte 81bc2117b2 listview: Implement GtkOrientable 2019-12-15 21:10:28 +01:00
Benjamin Otte f307f99275 tests: Add a rough form of multiselection
Just store a "filechooser::selected" attribute in the GFileInfo if
the file is meant to be selected.
2019-12-15 21:10:28 +01:00
Benjamin Otte 8157408df8 listview: Implement extending selections
Shift-clicking to extend selections now also works, imitating the
behavior of normal clicking and Windows Explorer (but not treeview):

1. We track the last selected item (normally, not via extend-clicking).

2. When shift-selecting, we modify the range from the last selected item
   to this item the same way we modify the regular item when not using
   shift:

2a. If Ctrl is not pressed, we select the range and unselect everything
    else.

2b. If Ctrl is pressed, we make the range have the same selection state
    as the last selected item:
    - If the last selected item is selected, select the range.
    - If the last selected item is not selected, unselect the range.
2019-12-15 21:10:28 +01:00
Benjamin Otte 9630b9f244 listview: Add list.scroll_to_item action
The action scrolls the given item into view.

Listitems activate this action when they gain focus.
2019-12-15 21:10:28 +01:00
Benjamin Otte 4b277dd47a testlistview: Load icons async
Speeds up loading by 4x, because out of view icons aren't loaded
anymore.
2019-12-15 21:10:28 +01:00
Benjamin Otte 5fcdf00a1a testlistview: Port to directory list 2019-12-15 21:10:28 +01:00
Benjamin Otte 48e1a3cc06 listitemfactory: Add a factory for ui files
Reuse <template> magic to initialize GtkListItems. This feels
amazingly hacky, but it also amazingly worked on the first try.
2019-12-15 21:10:28 +01:00
Benjamin Otte 8c5b077555 listitemfactory: Split implementation out
.. into gtkfunctionslistitemfactory.c

Now we can add a different implmenetation.
2019-12-15 21:10:28 +01:00
Benjamin Otte 023ff509b2 listitemfactory: vfuncify
No functional changes other than a new indirection.
2019-12-15 21:10:28 +01:00
Benjamin Otte a0a7da2e3b listitemfactory: Sanitize APIs
Make sure the APIs follow a predictable path:

setup
  bind
    rebind/update (0-N times)
  unbind
teardown

This is the first step towards providing multiple different factories.
2019-12-15 21:10:28 +01:00
Benjamin Otte b7ae37ab3d listview: Add gtk_list_view_set_show_separators()
Do the same thing that GtkListBox does in commit
0249bd4f8a
2019-12-15 21:10:28 +01:00
Benjamin Otte 6d8c6bb2f7 listitemmanager: Add trackers
... and replace the anchor tracking with a tracker.

Trackers track an item through the list across changes and ensure that
this item (and potentially siblings before/after it) are always backed
by a GtkListItem and that if the item gets removed a replacement gets
chosen.

This is now used for tracking the anchor but can also be used to add
trackers for the cursor later.
2019-12-15 21:10:28 +01:00
Benjamin Otte b00c04a986 listitemmanager: Simplify
Remove a bunch of API from the headers that isn't used anymore and then
refactor code to not call it anymore.

In particular, get rid of GtkListItemManagerChange and replace it with a
GHashTable.
2019-12-15 21:10:28 +01:00
Benjamin Otte 62da088018 gridview: Implement GtkScrollable
We can now scroll all the nothing we display.

We also clip it properly.
2019-12-15 21:10:28 +01:00
Benjamin Otte 6d93197f08 listitemmanager: Move list of listitems here
All the listview infrastructure moved with it, so the next step is
moving that back...
2019-12-15 21:10:28 +01:00
Benjamin Otte 72ce2ff512 wayland: Remove function declaration for nonexisting function 2019-12-15 21:10:28 +01:00
Benjamin Otte cfd503893c gridview: Add API for setting number of columns
The API isn't used yet.
2019-12-15 21:10:28 +01:00
Benjamin Otte a2ec02875a gtk: Add a GtkGridView skeleton 2019-12-15 21:10:28 +01:00
Benjamin Otte 07036e28c0 listitem: Add a press gesture to select the item
This is implemented by using actions, which are a neat trick to get to
allow the ListItem to call functions on the ListView without actually
needing to be aware of it.
2019-12-15 21:10:28 +01:00
Benjamin Otte 0b3135bf14 listview: Add initial support for displaying selections 2019-12-15 21:10:28 +01:00
Benjamin Otte 2ea5607f79 listview: Reset listitems' CSS animations when rebinding
This way, newly displayed rows don't play an unselect animation (text
fading in) when they are unselected, but the row was previously used for
a selected item.
2019-12-15 21:10:28 +01:00
Benjamin Otte 35e516f996 listview: Add selection properties to ListItem
This just brings the infrastructure into place, we're not using the
properties yet.
2019-12-15 21:10:28 +01:00
Benjamin Otte b856fe66b9 listview: Try to keep the list items in order when scrolling
Instead of just destroying all items and then recreating them (or even
hide()ing and then show()ing them again (or even even repositioning
them in the widget tree)), just try to reust them in the order they are.

This works surprisingly well when scrolling and most/all widgets
just moved.
2019-12-15 21:10:28 +01:00
Benjamin Otte 7d01e25558 listlistmodel: Add gtk_list_list_model_item_moved()
Use it to fix a case that just said g_warning ("oops").

Apparently I had forgotten the case where a container moved a child
in the widget tree.
2019-12-15 21:10:28 +01:00
Benjamin Otte b99db2a60b listitemmanager: Switch from "insert_before" to "insert_after" argumnet
We reorder widgets start to end, so when reusing a list item, we
correctly know the previous sibling for that list item, but not the
next sibling yet. We just know the widget it should ultimately be in
front of.
So we can do a more correct guess of the list item's place in the widget
tree if we think about where to place an item like this.

Actually using this change will come in the next commit.
2019-12-15 21:10:28 +01:00
Benjamin Otte 085e4ad273 testlistview: Create widgets only once
Previously, we were recreating all widgets every time the list item was
rebound, which caused a lot of extra work every time we scrolled.

Now we keep the widgets around and only set their properties again when
the item changes.
2019-12-15 21:10:28 +01:00
Benjamin Otte 72dea0d5e9 testlistview: Show the row number
Always show the current row. This is mostly useful for debugging, not
for beauty.
2019-12-15 21:10:28 +01:00
Benjamin Otte 6dd18fafaa listview: Only allocate necesary rows
This is the big one.

The listview only allocates 200 rows around the visible row now.
Everything else is kept in ListRow instances with row->widget == NULL.

For rows without a widget, we assign the median height of the child
widgets as the row's height and then do all calculations as if there
were widgets that had requested that height (like setting adjustment
values or reacting to adjustment value changes).

When the view is scrolled, we bind the 200 rows to the new visible area,
so that the part of the listview that can be seen is always allocated.
2019-12-15 21:10:28 +01:00
Benjamin Otte 9b9aec360e listview: Change anchor handling again
The anchor is now a tuple of { listitem, align }.

Using the actual list item allows keeping the anchor across changes
in position (ie when lists get resorted) while still being able to fall
back to positions (list items store their position) when an item gets
removed.

The align value is in the range [0..1] and defines where in the visible
area to do the alignment.
0.0 means to align the top of the row with the top of the visible area,
1.0 aligns the bottom of the widget with the visible area and 0.5 keeps
the center of the widget at the center of the visible area.
It works conceptually the same as percentages in CSS background-position
(where the background area and the background image's size are matched
the same way) or CSS transform-origin.
2019-12-15 21:10:28 +01:00
Benjamin Otte 0db67c9709 listview: Change how binding is done
We now don't let the functions create widgets for the item from the
listmodel, instead we hand out a GtkListItem for them to add a widget
to.

GtkListItems are created in advance and can only be filled in by the
binding code by gtk_container_add()ing a widget.
However, they are GObjects, so they can provide properties that the
binding code can make use of - either via notify signals or GBinding.
2019-12-15 21:10:28 +01:00
Benjamin Otte c935bf5648 listitem: Add gtk_list_item_get_position()
Also refactor the whole list item management yet again.

Now, list item APIs doesn't have bind/unbind functions anymore, but only
property setters.

The item factory is the only one doing the binding.
As before, the item manager manages when items need to be bound.
2019-12-15 21:10:28 +01:00
Benjamin Otte 94a9752c43 tests: Make animating listview do random resorts 2019-12-15 21:10:28 +01:00
Benjamin Otte de005bd1d6 listview: Change change management
Add a GtkListItemManagerChange object that tracks all removed list
rows during an item-changed signal so they can be added back later.
2019-12-15 21:10:28 +01:00
Benjamin Otte 134db60479 listview: Make the listitemmanager stricter
Require that items created with the manager get destroyed via the
manager.

To that purpose, renamed create_list_item() to acquire_list_item() and
add a matching release_list_item() function.

This way, the manager can in the future keep track of all items and
cache information about them.
2019-12-15 21:10:28 +01:00
Benjamin Otte 662b142c86 listview: Add GtkListItem
GtkListItem is a generic row widget that is supposed to replace
GtkListBoxRow and GtkFlowBoxChild.
2019-12-15 21:10:28 +01:00
Benjamin Otte 22a9001103 listview: Add GtkListItemManager
It's all stubs for now, but here's the basic ideas about what
this object is supposed to do:

(1) It's supposed to be handling all the child GtkWidgets that are
    used by the listview, so that the listview can concern
    itself with how many items it needs and where to put them.
(2) It's meant to do the caching of widgets that are not (currently)
    used.
(3) It's meant to track items that remain in the model across
    items-changed emissions and just change position.
(2) It's code that can be shared between listview and potential
    other widgets like a GridView.

It's also free to assume that the number of items it's supposed to
manage doesn't grow too much, so it's free to use O(N) algorithms.
2019-12-15 21:10:28 +01:00
Benjamin Otte 42b62c7ba2 listview: Implement an anchor
The anchor selection is very basic: just anchor the top row.

That's vastly better than any other widget already though.
2019-12-15 21:10:28 +01:00
Benjamin Otte 8bf19f7cbf tests: Add a test for a permanently changing listview
This is mostly for dealing with proper anchoring and can be used to
check that things don't scroll or that selection and focus handling
properly works.

For comparison purposes, a ListBox is provided next to it.
2019-12-15 21:10:28 +01:00
Benjamin Otte 15dce5c26c listview: Implement GtkScrollable
Scrolling in a very basic form is also supported
2019-12-15 21:10:28 +01:00
Benjamin Otte 742dfd919d listview: Make widget actually do something
The thing we're actually doing is create and maintain a widget for every
row. That's it.

Also add a testcase using this. The testcase quickly allocates too many
rows though and then becomes unresponsive though. You have been warned.
2019-12-15 21:10:28 +01:00
Benjamin Otte b5e54c1e7d listview: Introduce GtkListItemFactory
Thisis the abstraction I intend to use for creating widgets and binding
them to the item out of the listview.

For now this is a very dumb wrapper around the functions that exist in
the API.

But it leaves the freedom to turn this into public API, make an
interface out of it and most of all write different implementations, in
particular one that uses GtkBuilder.
2019-12-15 21:10:28 +01:00
Benjamin Otte 9756330b75 gtk: Add a GtkListView skeleton 2019-12-15 21:10:28 +01:00
Benjamin Otte 8126b24a78 builder: Add <binding> tag
The tag contains an expression that it then gtk_expression_bind()s to
the object it is contained in.
2019-12-15 21:10:28 +01:00
Benjamin Otte 9520a04d26 builder: Allow text content in <lookup>
<lookup>foo</lookup>
is now short for
  <lookup>
    <constant>foo</constant>
  </lookup>
ie it looks up the object with the given name so it can then do a
property lookup with it.

This is the most common operation, so it's a nice shortcut.
2019-12-15 21:10:28 +01:00
Benjamin Otte aa1d21a7ae builder: Allow <constant> without a type
A constant without a type is assumed to be an object. This is the most
common case and allows
  <constant>foo</constant>
without requiring updates to the type whenever the foo object changes.
2019-12-15 21:10:28 +01:00
Benjamin Otte 1c354586d0 builder: Make <lookup> type optional
If no type is set, use the type of the expression.
2019-12-15 21:10:28 +01:00
Benjamin Otte 90277fba71 gtk-demo: Make fishbowl info text use bindings
It's a good demo for how bindings can format multiple properties into an
informative string with 1 line of code (and 5 lines of XML).
2019-12-15 21:10:28 +01:00
Matthias Clasen 830939d8c7 sorter: Add tests
Some basic tests for GtkSorter.
2019-12-15 21:10:28 +01:00
Benjamin Otte 900616ec7a sortlistmodel: Make sort stable
The sort of the sortlistmodel is now stable with respect to the original
list model.

That means that if the sorter compares items as equal, the model
will make sure those items keep the order they were in in the original
model.

Or in other words: The model guarantees a total order based on the
item's position in the original model.
2019-12-15 21:10:28 +01:00
Benjamin Otte 2c047aa76f sortlistmodel: Redo the way we store the items
We need to keep this data around for changes in future commits where we
make the sorting stable.

An important part of the new data handling is that the unsorted list
needs to always be dealt with before the sorted list - upon creation we
rely on the unsorted iter and upon destruction, the sorted sequence
frees the entry leaving the unsorted sequence pointer invalid.

This change does not do any behavioral changes.
2019-12-15 21:10:28 +01:00
Matthias Clasen c1071d8c5d Redo sort list model with GtkSorter
Reshuffle the api to take full advantage
of GtkSorter. Update all callers.
2019-12-15 21:10:28 +01:00
Matthias Clasen 7c9ebaef3d Add GtkNumericSorter
This sorter compares numbers obtained from items
by evaluating an expression.
2019-12-15 21:10:28 +01:00
Matthias Clasen 90c75c8b9a Add GtkMultiSorter
This is a sorter that tries multiple sorters in turn.
2019-12-15 21:10:28 +01:00
Matthias Clasen 3c96f65094 Add GtkStringSorter
This is a GtkSorter implementation collating strings
2019-12-15 21:10:28 +01:00
Matthias Clasen 06fbc82ddf Add GtkCustomSorter
This is a GtkSorter implementation which uses a GCompareDataFunc.
2019-12-15 21:10:28 +01:00
Matthias Clasen 575b42c481 Add GtkSorter
This is a helper object for sorting, similar to GtkFilter.
2019-12-15 21:10:28 +01:00
Benjamin Otte 10631c979d Add GtkOrdering
This is an enum that we're gonna use soon and it's worth introducing as a
separate commit.

The intention is to have meaningful names for return values in
comparison functions.
2019-12-15 21:10:28 +01:00
Matthias Clasen c4ce8ef60f More expression tests
Test type mismatches, and the this pointer
during evaluation.
2019-12-15 21:10:28 +01:00
Benjamin Otte 04df027567 expression: Invalidate bindings before destroying them
Use a weak ref to invalidate bindings. Make sure that this happens
before creating any watches, so that notifies from the
watched expression about changes will not trigger set_property() calls
during dispose()/finalize().

Invalidating also ensures that the watches aren't removed, which can
trigger warnings if the watches are watching the object itself, and the
weak refs cannot be removed anymore.
2019-12-15 21:10:28 +01:00
Benjamin Otte fc0751a909 expression: Add gtk_expression_bind()
Add a simple way to bind expressions to object properties. This is
essentially the thing to replace g_object_bind_property().
2019-12-15 21:10:28 +01:00
Benjamin Otte 03815102d5 testsuite: Add expression tests 2019-12-15 21:10:28 +01:00
Benjamin Otte e8613aab9c expression: Add the ability to watch an expression 2019-12-15 21:10:28 +01:00
Benjamin Otte b603f472ab builder: Add support for parsing expressions 2019-12-15 21:10:28 +01:00
Benjamin Otte b4b6be9f6e filter: Add tests
Some basic tests for GtkFilter
2019-12-15 21:10:28 +01:00
Benjamin Otte bb12d3d8ca Add GtkMultiFilter, GtkAnyFilter, GtkEveryFilter
GtkMultiFilter is the abstract base class for managing multiple child
filter.
GtkAnyFilter and GtkEveryFilter are the actual implementations.
2019-12-15 21:10:28 +01:00
Benjamin Otte 52e385672a filter: Add GtkStringFilter
Users provide a search filter and an expression that evaluates the items
to a string and then the filter goes and matches those strings to the
search term.
2019-12-15 21:10:28 +01:00
Benjamin Otte ca2ebaf90f expression: Make property expression allow subexpressions 2019-12-15 21:10:28 +01:00
Benjamin Otte 46c042ed06 expression: Add GtkObjectExpression
Weak refs break cycles...
2019-12-15 21:10:27 +01:00
Benjamin Otte e462a2bdcc Add GtkExpression
GtkExpressions allow looking up values from objects.

There are a few simple expressions, but the main one is the closure
expression that just calls a user-provided closure.
2019-12-15 21:10:27 +01:00
Benjamin Otte bb59b48871 filterlistmodel: Rewrite to use GtkFilter 2019-12-15 21:10:27 +01:00
Benjamin Otte da413fa72d tests: Remove testtreemodel test
testlistview does everything this test does.
2019-12-15 21:10:27 +01:00
Benjamin Otte 75556a3485 Add GtkCustomFilter 2019-12-15 21:10:27 +01:00
Benjamin Otte 53401e5d89 Add GtkFilter 2019-12-15 21:10:27 +01:00
Benjamin Otte 56838cab86 Add GtkDirectoryList
Adds a new listmodel called GtkDirectoryList that lists the children of
a GFile as GFileInfos.

This is supposed to be used by the filechooser.
2019-12-15 21:10:27 +01:00
Benjamin Otte 0a551b9b2a gdk: Add GDK_DECLARE_EXPORTED_TYPE()
This is like G_DECLARE_FINAL_TYPE(), except it doesn't make the class
struct public, so internally all the subclassing in the world can
happen.

Some subtle differences:
- It marks the get_type() function as G_GNUC_CONST
- It doesn't require the parent type
- It uses G_DEFINE_AUTOPTR_CLEANUP_FUNC() instead of the private glib
  chainup method.

Port a bunch of GDK and the whole event controller + gesture machinery
to provew that it works.

As a side effect, we gained a bunch of missing autocleanups.
2019-12-15 21:10:27 +01:00
Benjamin Otte ed24f93fb9 popover: Remove unneeded vfunc
The vfunc is identical to the GtkWidget implementation it replaces. So
just keep using that one.
2019-12-15 21:07:54 +01:00
Benjamin Otte c4043a8eef treelistmodel: Improve docs
- Move into its own section
- Split GtkTreeListRow into its own document

Trees are weird with listmodels and they deserve their own treatment,
they shouldn't be mushed up with the rest of the list machinery.
2019-12-15 21:07:54 +01:00
Benjamin Otte dff86c0e12 eventcontrollermotion: Add getters for the properties
... and use them.

Also, rename them from is/contains-pointer-focus to is/contains-pointer,
that's clear enough and not too long.

Finally, adapt the semantics of contains-pointer to mirror
GtkEventControllerKey::contains-focus. If is-pointer is set, so is
contains-pointer, they are not exclusive.
Which is what all users of this property wanted, too.
2019-12-15 21:07:54 +01:00
Matthias Clasen 9a5ec33d61 Merge branch 'fix-x11-cursor-crash' into 'master'
x11: Only update cursors if we have any

Closes #2308

See merge request GNOME/gtk!1249
2019-12-13 20:02:43 +00:00
Matthias Clasen 78227bf5b0 Merge branch 'matthiasc/for-master' into 'master'
some builder-tool improvements

See merge request GNOME/gtk!1248
2019-12-13 19:58:53 +00:00
Matthias Clasen bf2c29a36a x11: Only update cursors if we have any
We were accessing an on-demand created hash table
without checking if it had been created first.

Fixes: https://gitlab.gnome.org/GNOME/gtk/issues/2308
2019-12-13 14:46:00 -05:00
Matthias Clasen 47285c6642 builder: Improve type name mangling
When looking for the get_type function for GThemedIcon,
try both g_themed_icon_get_type and gthemed_icon_get_type
The former is what gio has, the latter is still supported
to avoid breaking gweather_location_get_type.

Update tests to cover this new case.
2019-12-13 14:21:44 -05:00
Matthias Clasen e4fb4116fd builder-tool: Don't try to find default boxed values
This doesn't work and yields an ugly, unnecessary
error message.
2019-12-13 14:21:44 -05:00
Matthias Clasen 6d3373cb2c gtk-builder-tool: More helpful error messages
Include line numbers in the error messages we
report, so it is possible to find the error.
2019-12-13 14:21:44 -05:00
Marek Kasik 6ddc214e68 printing: Fill device URI for non-Avahi printers
Device URI was not filled for non-Avahi printers by my previous commit.
I've added it back. It was a mistake during rebasing of the patch
to current master.
2019-12-13 17:53:14 +01:00
Matthias Clasen 91a802a1e5 Merge branch '1509-don-t-show-Rejecting-Jobs-when-we-don-t-know' into 'master'
Fix getting info for standalone IPP printers

Closes #1509

See merge request GNOME/gtk!1247
2019-12-13 16:13:17 +00:00
Daniel Mustieles 886ab54eda Updated Spanish translation 2019-12-13 12:24:36 +01:00
Matthias Clasen 4470e5bc93 gtk-demo: Some touchups
Make the theming style classes demo look a bit less odd.
2019-12-12 18:46:53 -05:00
Matthias Clasen 9bbacd3e4c Run gtk-builder-tool simplify over our ui files
This was done mainly to verify that the tool does not
make any unwarranted changes. The changes included here
are all cosmetic.
2019-12-12 18:37:39 -05:00
Matthias Clasen 353df67c0b Add GtkNative to the docs
It was not included in the generated docs.
2019-12-12 18:21:16 -05:00
Matthias Clasen 050eb9ba73 Fix up GtkBuilderScope docs
They were not hooked into the document generation.
2019-12-12 18:18:49 -05:00
Matthias Clasen 4fa5f5497a builder: Another small docs fix 2019-12-12 17:59:24 -05:00
Matthias Clasen 21a032b783 docs: Ignore more private headers 2019-12-12 17:59:24 -05:00
Matthias Clasen 207efd8932 docs: Remove symbols that no longer exist 2019-12-12 17:59:24 -05:00
Matthias Clasen 43c943e48a Merge branch 'issue-179' into 'master'
Use a separate gesture for middle clicks on PlaceView rows

Closes #179

See merge request GNOME/gtk!1199
2019-12-12 22:53:36 +00:00
Matthias Clasen d6dc5da6db textbuffer: Minor doc fixes
Fix parameter name mismatches.
2019-12-12 17:31:13 -05:00
Matthias Clasen 12d787286e builder: Minor doc fixes
Fix parameter name mismatches.
2019-12-12 17:30:36 -05:00
Matthias Clasen c33a7670d0 Merge branch 'wip/otte/builder' into 'master'
More builder work

Closes #2267

See merge request GNOME/gtk!1230
2019-12-12 20:36:08 +00:00
Matthias Clasen bbb56d8216 Merge branch 'file-transfer' into 'master'
clipboard: file transfer portal support

See merge request GNOME/gtk!1244
2019-12-12 19:33:02 +00:00
Matthias Clasen a20c8af678 clipboard: file transfer portal support
Implement file-list <-> application/vnd.flatpak.file-list
serialization by talking to the file transfer portal.

See https://github.com/flatpak/xdg-desktop-portal/pull/222
2019-12-12 14:25:33 -05:00
Matthias Clasen 0eb2b382a2 Merge branch 'master-gitlab-HC-tooltip' into 'master'
Set HighContrast tooltip back to black text over white background

See merge request GNOME/gtk!1242
2019-12-12 19:18:06 +00:00
Benjamin Otte 101298c54d gtk-demo: Don't include "gtk.h" 2019-12-12 19:50:55 +01:00
Benjamin Otte f6bdfc32d3 tests: Set an existing font in testfontchooser 2019-12-12 19:50:55 +01:00
Benjamin Otte 5015730212 builder: Turn last dlsym() function into a scope API
Looking up a get_type function by its name is now also part of
GtkBuilderScope.
2019-12-12 19:39:36 +01:00
Benjamin Otte f8a7f30a0d builder: Add GtkBuilderScope
GtkBuilderScope is an interface that provides the scope that a builder
instance operates in.
It creates closures and resolves types. Language bindings are meant to
use this interface to customize the behavior of builder files, in
particular when instantiating templates.

A default implementation for C is provided via GtkBuilderCScope (to keep
with the awkward naming that glib uses for closures). It is derivable on
purpose so that languages or extensions that extend C can use it.

The reftest code in fact does derive GtkBuilderCScope for its own scope
implementation that implements looking up symbols in modules.

gtk-widget-factory was updated to use the new GtkBuilderCScope to add
its custom callback symbols.
So it does it different from gtk-demo, which uses the normal way of
exporting symbols for dlsym() and thereby makes the 2 demos test the 2
ways GtkBuilder uses for looking up symbols.
2019-12-12 19:39:23 +01:00
Benjamin Otte 1f94028ff7 builder: Add gtk_builder_set_current_object()
Use it as the default object for expression binds and when connecting
signals. It is intended to work kind of as the "this" object while
parsing. In fact, the term "current object" was stolen from the Java
docs and various C++ tutorials for the this pointer.

Set the current object in gtk_widget_init_template() and
GtkListItemBuilder.

This more-or-less replaces the object passed to
gtk_builder_connect_signals() in GTK3.
2019-12-12 19:12:11 +01:00
Benjamin Otte 512c4c13a6 builder: Add gtk_builder_lookup_object()
... and use it. This function looks up an object like
gtk_builder_get_object() but generates an error on failure.

Unlike the evil function _gtk_builder_lookup_object() which also
generates an error but hides it for later lookup.

Use this to avoid continuing applying properties when an error was
encountered.
2019-12-12 19:12:11 +01:00
Benjamin Otte 552db7cb08 types: Move GTK_INVALID_LIST_POSITION here
I have no idea where it should go really - maybe glib?

It certainly shouldn't require everybody including selectionmodel code
just to get at this value.
2019-12-12 19:10:45 +01:00
Matthias Clasen d564cb2a7e Merge branch 'terminal' into 'master'
imwayland: Suppport terminal purpose

See merge request GNOME/gtk!1243
2019-12-12 17:57:05 +00:00
Marek Kasik a6e3fc2d2f printing: Fix getting info for standalone IPP printers
Create printer name from name of the advertised service
for standalone IPP printers as opposed to CUPS printers
advertised via Avahi which get name from their
resource path.
This is similar to what cups-filters does.

Pass GtkPrinter class to request for printer info
so that it does not need to be searched for
(such search could fail for standalone IPP printers).

https://gitlab.gnome.org/GNOME/gtk/issues/1509
2019-12-12 17:08:30 +01:00
Marek Kasik e54049bc26 printing: Don't show Rejecting Jobs when we don't know
Set reasonable default values for printers discovered
by Avahi which do not have 'printer-type' attribute.
This is the case for network printers which were not
published by CUPS.

Related to the issue #1509.
2019-12-12 17:08:30 +01:00
Dorota Czaplejewicz e331b39ca5 imwayland: Suppport terminal purpose 2019-12-12 14:37:51 +00:00
Jonathan Michalon e6270ca43f Set HighContrast tooltip back to black text over white background
8abdbfee16 pulled Adwaita tooltip selectors,
but in the meantime the colors were also set to Adwaita's. Push back the same
behaviour as before because it's better for visually-impaired users.
2019-12-12 09:51:40 +01:00
Christoph Reiter 88da95d921 Merge branch 'honor-hotspot-gtk4' into 'master'
gdk/x11: Honor hotspot during drag cancel animation

See merge request GNOME/gtk!1236
2019-12-11 12:59:23 +00:00
Chun-wei Fan 44f9c67466 Merge branch 'vulkan-no-layered-windows' into 'master'
Win32: Do not enable layered windows when using Vulkan

See merge request GNOME/gtk!1217
2019-12-11 06:24:49 +00:00
Matthias Clasen 02bbe399df Merge branch 'matthiasc/for-master' into 'master'
widget factory: Fix more grid layout fallout

See merge request GNOME/gtk!1237
2019-12-10 03:05:09 +00:00
Matthias Clasen 41bb40feee widget factory: Fix more grid layout fallout 2019-12-09 21:29:03 -05:00
Benjamin Otte 336d652be5 a11y: We can peek here
Avoids instantiating a11y objects when we don't need to.
2019-12-09 16:35:41 +01:00
Benjamin Otte d3e8678955 treeview: Don't create a cyclic reference
TreeRowReference refs the proxy object, so don't use proxies.
2019-12-09 16:35:41 +01:00
Benjamin Otte 503d988c1b label: Compute label baselines correctly
When we were switching smallest and widest, we were not switching the
baselines.
2019-12-09 16:35:41 +01:00
Robert Mader 7a46378e71 gdk/x11: Honor hotspot during drag cancel animation
Otherwise the icon "jumps" to the cursor position with its top left when
the animation starts.
This is especially visible if the dragged item is big, like when dragging
mails in Thunderbird.
2019-12-09 01:45:30 +01:00
Matthias Clasen 9f6d12551f Add GtkTreeListRow type to the docs 2019-12-08 17:58:09 -05:00
Matthias Clasen 43c93d6f85 Add missing listmodel and selection types to the docs 2019-12-08 13:56:47 -05:00
Matthias Clasen d683d085c0 tree list model: Add a missing annotation
The GtkTreeListModelCreateModelFunc returns
a new reference.
2019-12-08 00:30:32 -05:00
Matthias Clasen 92ab450983 inspector: Avoid critical warnings
We were still using this but it's not defined in the UI xml.

Fixes: https://gitlab.gnome.org/GNOME/gtk/issues/2295
2019-12-07 19:39:02 -05:00
Matthias Clasen 7b14c65b41 Merge branch 'inspector-display' into 'master'
Inspector display

See merge request GNOME/gtk!1234
2019-12-07 23:20:51 +00:00
Matthias Clasen c89c652401 inspector: Make the css tree respect inspected display
The display is used here to force reparsing the theme
on the right settings object.
2019-12-07 18:07:44 -05:00
Matthias Clasen f0f57d156b inspector: Make logs respect inspected display 2019-12-07 18:07:05 -05:00
Matthias Clasen cecf4f2763 inspector: Make inspect button use inspected display
This may not matter, but just for cleanliness.
2019-12-07 18:07:05 -05:00
Matthias Clasen 4eeed47c7b inspector: Make general respect inspected display 2019-12-07 18:07:05 -05:00
Matthias Clasen bd1f7e057a inspector: Make visual settings respect the inspected display
This is not quite complete, GTK and GSK debug flags
are not per display, and slowdown and text direction
are not either.
2019-12-07 18:07:05 -05:00
Matthias Clasen 174d8b72a5 inspector: Make css editor respect inspected display
Stop using gdk_display_get_default and use the
inspected display instead.
2019-12-07 18:07:05 -05:00
Matthias Clasen 1437b0856c inspector: Make object tree respect inspected display
Stop using gdk_display_get_dfault and use the
inspected display instead.
2019-12-07 14:59:49 -05:00
Matthias Clasen 917181cb67 window: Get rid of the inspector_window static
Use the new per-display inspector plumbing and
stop relying on a static variable.
2019-12-07 14:59:49 -05:00
Matthias Clasen a207a4b3cd inspector: Attach inspector window to display
Give the inspector window a ::inspected-display
property, and pass a display when obtaining an
inspector window. Update the caller.
2019-12-07 14:59:49 -05:00
Matthias Clasen 39a1d27960 window: Inspector cleanups
Reduce the use of the inspector_window static.
The goal is to have one inspector window per
display, so we need to get rid of the static.
2019-12-07 14:59:49 -05:00
Matthias Clasen 5ef4a64084 window: Remove inspector updating fully
Commit 05e752e096 left some ruins behind.
Clean that up.
2019-12-07 14:59:49 -05:00
Matthias Clasen baacd9efbf inspector: Init yourself
No need to have GTK call this from the outside.
2019-12-07 14:59:49 -05:00
Matthias Clasen abde37a4d7 inspector: Cleanup
Remove an unused enum.
2019-12-07 14:59:49 -05:00
Matthias Clasen 3ee9b0cf4b Make a test with a custom display
This completely breaks the inspector.
2019-12-07 10:03:42 -05:00
Matthias Clasen 88049915a2 Merge branch 'doc-update' into 'master'
doc: Cleanup doc removing mentions of gdk_surface_shape_combine_region()

See merge request GNOME/gtk!1232
2019-12-05 22:11:31 +00:00
Hubert Figuière 585397937d doc: Cleanup doc removing mentions of gdk_surface_shape_combine_region() 2019-12-05 11:33:09 -05:00
Matthias Clasen 256b6f1aff Merge branch 'matthiasc/for-master' into 'master'
fix leaks in the testsuite

See merge request GNOME/gtk!1231
2019-12-05 00:01:23 +00:00
Matthias Clasen acabdafb35 Fix treelistmodel tests
They were failing to return a reference where they
need to. This was uncovered by fixing an unrelated
ref leak.
2019-12-04 18:30:37 -05:00
Matthias Clasen 168c1f440d Fix leaks in tests
All the list model tests were leaking items,
because g_list_model_get_item is transfer full.

Fixing these unveils a crash in the treelistmodel
and maplistmodel tests.
2019-12-04 18:24:56 -05:00
Tim Sabsch 33a8ef4bce Update German translation 2019-12-04 19:37:01 +00:00
Chun-wei Fan 9c5ea8eba4 gdkvulkancontext-win32.c: Suppress layered Windows on Vulkan
The Vulkan renderer does not work well with layered windows enabled, so
turn it off when we successfully created the Vulkan context on Windows.
2019-11-26 17:00:11 +08:00
Emmanuele Bassi 04bb5aad36 Use a separate gesture for middle clicks on PlaceView rows
The click gesture in GtkListBox is exclusively for primary button
clicks; this means we're never going to get a click from the middle
button. We need to use a separate GtkGestureClick controller for middle
clicks, in order to activate rows with the 'open-in-tab' flag.

Fixes: #179
2019-11-25 16:02:40 +00:00
243 changed files with 23032 additions and 6047 deletions
File diff suppressed because it is too large Load Diff
+4
View File
@@ -131,6 +131,9 @@
<gresource prefix="/listview_weather">
<file compressed="true">listview_weather.txt</file>
</gresource>
<gresource prefix="/listview_colors">
<file compressed="true">color.names.txt</file>
</gresource>
<gresource prefix="/shortcuts">
<file>shortcuts.ui</file>
<file>shortcuts-builder.ui</file>
@@ -211,6 +214,7 @@
<file>links.c</file>
<file>listbox.c</file>
<file>listview_applauncher.c</file>
<file>listview_colors.c</file>
<file>listview_clocks.c</file>
<file>listview_filebrowser.c</file>
<file>listview_minesweeper.c</file>
+2
View File
@@ -4,6 +4,8 @@
* as needed and support sorting and filtering.
*
* The children of a GtkFlowBox are regular widgets
*
* The dataset used here has 665 colors.
*/
#include <gtk/gtk.h>
-2
View File
@@ -19,8 +19,6 @@
#include "fontplane.h"
#include "gtk.h"
enum {
PROP_0,
PROP_WEIGHT_ADJUSTMENT,
+4 -3
View File
@@ -165,10 +165,11 @@
</child>
<child>
<object class="GtkBox">
<property name="orientation">horizontal</property>
<property name="halign">center</property>
<property name="valign">center</property>
<style><class name="linked"/></style>
<style>
<class name="linked"/>
</style>
<child>
<object class="GtkRadioButton" id="text_radio">
<property name="draw-indicator">0</property>
@@ -183,7 +184,7 @@
</object>
</child>
<layout>
<property name="left-attach">0</property>
<property name="left-attach">0</property>
<property name="top-attach">3</property>
<property name="column-span">7</property>
</layout>
+50 -1
View File
@@ -12,7 +12,7 @@ static GtkWidget *window = NULL;
static GtkWidget *scrolledwindow;
static int selected;
#define N_WIDGET_TYPES 4
#define N_WIDGET_TYPES 6
static int hincrement = 5;
@@ -61,6 +61,7 @@ populate_icons (void)
gtk_grid_attach (GTK_GRID (grid), create_icon (), left, top, 1, 1);
hincrement = 0;
vincrement = 5;
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
GTK_POLICY_NEVER,
@@ -97,6 +98,7 @@ populate_text (gboolean hilight)
gtk_text_view_set_buffer (GTK_TEXT_VIEW (textview), buffer);
hincrement = 0;
vincrement = 5;
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
GTK_POLICY_NEVER,
@@ -121,6 +123,7 @@ populate_image (void)
gtk_picture_set_can_shrink (GTK_PICTURE (image), FALSE);
hincrement = 5;
vincrement = 5;
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
GTK_POLICY_AUTOMATIC,
@@ -128,6 +131,42 @@ populate_image (void)
gtk_container_add (GTK_CONTAINER (scrolledwindow), image);
}
extern GtkWidget *create_weather_view (void);
static void
populate_list (void)
{
GtkWidget *list;
list = create_weather_view ();
hincrement = 5;
vincrement = 0;
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
gtk_container_add (GTK_CONTAINER (scrolledwindow), list);
}
extern GtkWidget *create_color_grid (void);
static void
populate_grid (void)
{
GtkWidget *list;
list = create_color_grid ();
hincrement = 0;
vincrement = 5;
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
gtk_container_add (GTK_CONTAINER (scrolledwindow), list);
}
static void
set_widget_type (int type)
{
@@ -162,6 +201,16 @@ set_widget_type (int type)
populate_image ();
break;
case 4:
gtk_window_set_title (GTK_WINDOW (window), "Scrolling a list");
populate_list ();
break;
case 5:
gtk_window_set_title (GTK_WINDOW (window), "Scrolling a grid");
populate_grid ();
break;
default:
g_assert_not_reached ();
}
+6 -3
View File
@@ -31,9 +31,12 @@
<child>
<object class="GtkScrolledWindow" id="scrolledwindow">
<property name="hscrollbar-policy">never</property>
<property name="vscrollbar-policy">automatic</property>
<property name="hadjustment"><object class="GtkAdjustment" id="hadjustment"/></property>
<property name="vadjustment"><object class="GtkAdjustment" id="vadjustment"/></property>
<property name="hadjustment">
<object class="GtkAdjustment" id="hadjustment"/>
</property>
<property name="vadjustment">
<object class="GtkAdjustment" id="vadjustment"/>
</property>
</object>
</child>
</object>
+14 -13
View File
@@ -8,8 +8,10 @@
#include <gtk/gtk.h>
/* This is the function that creates the #GListModel that we need.
* GTK list widgets need a #GListModel to display, as it support change
* notifications, but various older APIs do not support one.
* GTK list widgets need a #GListModel to display, as models support change
* notifications.
* Unfortunately various older APIs do not provide list models, so we create
* our own.
*/
static GListModel *
create_application_list (void)
@@ -73,7 +75,7 @@ bind_listitem_cb (GtkListItemFactory *factory,
}
/* In more complex code, we would also need functions to unbind and teardown
* the listitem, but this is simple code, so the default implemntations are
* the listitem, but this is simple code, so the default implementations are
* enough. If we had connected signals, this step would have been necessary.
*
* The #GtkSignalListItemFactory documentation contains more information about
@@ -150,29 +152,28 @@ do_listview_applauncher (GtkWidget *do_widget)
/* The #GtkListitemFactory is what is used to create #GtkListItems
* to display the data from the model. So it is absolutely necessary
* to create one.
* We will use a #GtkSignalListitemFactory because it is the simplest
* We will use a #GtkSignalListItemFactory because it is the simplest
* one to use. Different ones are available for different use cases.
* The most powerful one being the #GtkBuilderListItemFactory which
* will to everything without requiring any code and just using a
* #GtkBuilder .ui file.
* The most powerful one is #GtkBuilderListItemFactory which uses
* #GtkBuilder .ui files, so it requires little code.
*/
factory = gtk_signal_list_item_factory_new ();
g_signal_connect (factory, "setup", G_CALLBACK (setup_listitem_cb), NULL);
g_signal_connect (factory, "bind", G_CALLBACK (bind_listitem_cb), NULL);
/* Create the list widget here: We use a coverflow widgets, because it's
/* Create the list widget here: We use a coverflow widget because it's
* the coolest one. We could just as well use other list widgets such
* as a #GtkListView or a #GtkGridView and the code would look quite
* the same.
* as a #GtkListView or a #GtkGridView and the code would look very
* similar.
*/
coverflow = gtk_cover_flow_new_with_factory (factory);
/* We connect the activate signal here. It's the function you remember
* from above for launching the selected application.
/* We connect the activate signal here. It's the function we defined
* above for launching the selected application.
*/
g_signal_connect (coverflow, "activate", G_CALLBACK (activate_cb), NULL);
/* And of course we need to set the data model. Here we call the function
* we wrote above that gives us the list of applications and then we set
* we wrote above that gives us the list of applications. Then we set
* it on the coverflow list widget.
* The coverflow will now take items from the model and use the factory
* to create as many listitems as it needs to show itself to the user.
+10 -7
View File
@@ -2,11 +2,12 @@
*
* This demo displays the time in different timezones.
*
* The goal is to show how to set up expressions that track changes
* in objects and make them update widgets.
* It is using a GtkGridView.
*
* For that, we create a GtkClock object that updates its time every
* second and then use various ways to display that time.
* The goal is to show how to set up expressions that track changes
* in objects and make them update widgets. For that, we create a
* GtkClock object that updates its time every second and then use
* various ways to display that time.
*
* Typically, this will be done using GtkBuilder .ui files with the
* help of the <binding> tag, but this demo shows the code that runs
@@ -401,7 +402,7 @@ setup_listitem_cb (GtkListItemFactory *factory,
"location");
/* Now create the label and bind the expression to it. */
location_label = gtk_label_new (NULL);
gtk_expression_bind (expression, location_label, location_label, "label");
gtk_expression_bind (expression, location_label, "label", location_label);
gtk_container_add (GTK_CONTAINER (box), location_label);
@@ -411,7 +412,7 @@ setup_listitem_cb (GtkListItemFactory *factory,
expression = gtk_expression_ref (clock_expression);
/* Now create the widget and bind the expression to it. */
picture = gtk_picture_new ();
gtk_expression_bind (expression, picture, picture, "paintable");
gtk_expression_bind (expression, picture, "paintable", picture);
gtk_container_add (GTK_CONTAINER (box), picture);
@@ -430,7 +431,7 @@ setup_listitem_cb (GtkListItemFactory *factory,
NULL, NULL);
/* Now create the label and bind the expression to it. */
time_label = gtk_label_new (NULL);
gtk_expression_bind (expression, time_label, time_label, "label");
gtk_expression_bind (expression, time_label, "label", time_label);
gtk_container_add (GTK_CONTAINER (box), time_label);
gtk_expression_unref (clock_expression);
@@ -450,6 +451,8 @@ do_listview_clocks (GtkWidget *do_widget)
/* This is the normal window setup code every demo does */
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Clocks");
gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
g_signal_connect (window, "destroy",
+593
View File
@@ -0,0 +1,593 @@
/* Lists/Colors
*
* This demo displays a named colors.
*
* It is using a GtkGridView, and shows
* how to sort the data in various ways.
*
* The dataset used here has 9283 items.
*/
#include <gtk/gtk.h>
#define GTK_TYPE_COLOR (gtk_color_get_type ())
G_DECLARE_FINAL_TYPE (GtkColor, gtk_color, GTK, COLOR, GObject)
/* This is our object. It's just a color */
typedef struct _GtkColor GtkColor;
struct _GtkColor
{
GObject parent_instance;
char *name;
GdkRGBA *color;
int h, s, v;
};
enum {
PROP_0,
PROP_NAME,
PROP_COLOR,
PROP_RED,
PROP_GREEN,
PROP_BLUE,
PROP_HUE,
PROP_SATURATION,
PROP_VALUE,
N_PROPS
};
static void
gtk_color_snapshot (GdkPaintable *paintable,
GdkSnapshot *snapshot,
double width,
double height)
{
GtkColor *self = GTK_COLOR (paintable);
gtk_snapshot_append_color (snapshot, self->color, &GRAPHENE_RECT_INIT (0, 0, width, height));
}
static int
gtk_color_get_intrinsic_width (GdkPaintable *paintable)
{
return 32;
}
static int
gtk_color_get_intrinsic_height (GdkPaintable *paintable)
{
return 32;
}
static void
gtk_color_paintable_init (GdkPaintableInterface *iface)
{
iface->snapshot = gtk_color_snapshot;
iface->get_intrinsic_width = gtk_color_get_intrinsic_width;
iface->get_intrinsic_height = gtk_color_get_intrinsic_height;
}
/*
* Finally, we define the type. The important part is adding the paintable
* interface, so GTK knows that this object can indeed be drawm.
*/
G_DEFINE_TYPE_WITH_CODE (GtkColor, gtk_color, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
gtk_color_paintable_init))
static GParamSpec *properties[N_PROPS] = { NULL, };
static void
gtk_color_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
GtkColor *self = GTK_COLOR (object);
switch (property_id)
{
case PROP_NAME:
g_value_set_string (value, self->name);
break;
case PROP_COLOR:
g_value_set_boxed (value, self->color);
break;
case PROP_RED:
g_value_set_float (value, self->color->red);
break;
case PROP_GREEN:
g_value_set_float (value, self->color->green);
break;
case PROP_BLUE:
g_value_set_float (value, self->color->blue);
break;
case PROP_HUE:
g_value_set_int (value, self->h);
break;
case PROP_SATURATION:
g_value_set_int (value, self->s);
break;
case PROP_VALUE:
g_value_set_int (value, self->v);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
gtk_color_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
GtkColor *self = GTK_COLOR (object);
switch (property_id)
{
case PROP_NAME:
self->name = g_value_dup_string (value);
break;
case PROP_COLOR:
self->color = g_value_dup_boxed (value);
break;
case PROP_HUE:
self->h = g_value_get_int (value);
break;
case PROP_SATURATION:
self->s = g_value_get_int (value);
break;
case PROP_VALUE:
self->v = g_value_get_int (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
gtk_color_finalize (GObject *object)
{
GtkColor *self = GTK_COLOR (object);
g_free (self->name);
g_clear_pointer (&self->color, gdk_rgba_free);
G_OBJECT_CLASS (gtk_color_parent_class)->finalize (object);
}
static void
gtk_color_class_init (GtkColorClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->get_property = gtk_color_get_property;
gobject_class->set_property = gtk_color_set_property;
gobject_class->finalize = gtk_color_finalize;
properties[PROP_NAME] =
g_param_spec_string ("name", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
properties[PROP_COLOR] =
g_param_spec_boxed ("color", NULL, NULL, GDK_TYPE_RGBA, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
properties[PROP_RED] =
g_param_spec_float ("red", NULL, NULL, 0, 1, 0, G_PARAM_READABLE);
properties[PROP_GREEN] =
g_param_spec_float ("green", NULL, NULL, 0, 1, 0, G_PARAM_READABLE);
properties[PROP_BLUE] =
g_param_spec_float ("blue", NULL, NULL, 0, 1, 0, G_PARAM_READABLE);
properties[PROP_HUE] =
g_param_spec_int ("hue", NULL, NULL, 0, 360, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
properties[PROP_SATURATION] =
g_param_spec_int ("saturation", NULL, NULL, 0, 100, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
properties[PROP_VALUE] =
g_param_spec_int ("value", NULL, NULL, 0, 100, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_properties (gobject_class, N_PROPS, properties);
}
static void
gtk_color_init (GtkColor *self)
{
}
static GtkColor *
gtk_color_new (const char *name,
float r, float g, float b,
int h, int s, int v)
{
GtkColor *result;
GdkRGBA color = { r, g, b, 1.0 };
result = g_object_new (GTK_TYPE_COLOR,
"name", name,
"color", &color,
"hue", h,
"saturation", s,
"value", v,
NULL);
return result;
}
static GListModel *
create_colors_model (void)
{
GListStore *result;
GtkColor *color;
GBytes *data;
char **lines;
guint i;
result = g_list_store_new (GTK_TYPE_COLOR);
data = g_resources_lookup_data ("/listview_colors/color.names.txt", 0, NULL);
lines = g_strsplit (g_bytes_get_data (data, NULL), "\n", 0);
for (i = 0; lines[i]; i++)
{
const char *name;
char **fields;
int red, green, blue;
int h, s, v;
if (lines[i][0] == '#' || lines[i][0] == '\0')
continue;
fields = g_strsplit (lines[i], " ", 0);
name = fields[1];
red = atoi (fields[3]);
green = atoi (fields[4]);
blue = atoi (fields[5]);
h = atoi (fields[9]);
s = atoi (fields[10]);
v = atoi (fields[11]);
color = gtk_color_new (name, red / 255., green / 255., blue / 255., h, s, v);
g_list_store_append (result, color);
g_object_unref (color);
g_strfreev (fields);
}
g_strfreev (lines);
g_bytes_unref (data);
return G_LIST_MODEL (result);
}
static char *
get_rgb_markup (gpointer this,
GtkColor *color)
{
if (!color)
return NULL;
return g_strdup_printf ("<b>R:</b> %d <b>G:</b> %d <b>B:</b> %d",
(int)(color->color->red * 255),
(int)(color->color->green * 255),
(int)(color->color->blue * 255));
}
static char *
get_hsv_markup (gpointer this,
GtkColor *color)
{
if (!color)
return NULL;
return g_strdup_printf ("<b>H:</b> %d <b>S:</b> %d <b>V:</b> %d",
color->h,
color->s,
color->v);
}
static void
setup_simple_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, 32, 32);
gtk_expression_bind (color_expression, picture, "paintable", NULL);
gtk_list_item_set_child (list_item, picture);
}
static void
setup_listitem_cb (GtkListItemFactory *factory,
GtkListItem *list_item)
{
GtkWidget *box, *picture, *name_label, *rgb_label, *hsv_label;;
GtkExpression *color_expression, *expression;
GtkExpression *params[1];
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_list_item_set_child (list_item, box);
expression = gtk_constant_expression_new (GTK_TYPE_LIST_ITEM, list_item);
color_expression = gtk_property_expression_new (GTK_TYPE_LIST_ITEM, expression, "item");
expression = gtk_property_expression_new (GTK_TYPE_COLOR,
gtk_expression_ref (color_expression),
"name");
name_label = gtk_label_new (NULL);
gtk_expression_bind (expression, name_label, "label", NULL);
gtk_container_add (GTK_CONTAINER (box), name_label);
expression = gtk_expression_ref (color_expression);
picture = gtk_picture_new ();
gtk_expression_bind (expression, picture, "paintable", NULL);
gtk_container_add (GTK_CONTAINER (box), picture);
params[0] = gtk_expression_ref (color_expression);
expression = gtk_cclosure_expression_new (G_TYPE_STRING,
NULL,
1, params,
(GCallback)get_rgb_markup,
NULL, NULL);
rgb_label = gtk_label_new (NULL);
gtk_label_set_use_markup (GTK_LABEL (rgb_label), TRUE);
gtk_expression_bind (expression, rgb_label, "label", NULL);
gtk_container_add (GTK_CONTAINER (box), rgb_label);
params[0] = gtk_expression_ref (color_expression);
expression = gtk_cclosure_expression_new (G_TYPE_STRING,
NULL,
1, params,
(GCallback)get_hsv_markup,
NULL, NULL);
hsv_label = gtk_label_new (NULL);
gtk_label_set_use_markup (GTK_LABEL (hsv_label), TRUE);
gtk_expression_bind (expression, hsv_label, "label", NULL);
gtk_container_add (GTK_CONTAINER (box), hsv_label);
gtk_expression_unref (color_expression);
}
static void
set_title (gpointer item,
const char *title)
{
g_object_set_data (G_OBJECT (item), "title", (gpointer)title);
}
static char *
get_title (gpointer item)
{
return g_strdup ((char *)g_object_get_data (G_OBJECT (item), "title"));
}
static gboolean
set_item (GBinding *binding,
const GValue *from,
GValue *to,
gpointer data)
{
GObject *source = g_binding_get_source (binding);
GListModel *model;
guint selected;
gpointer item;
selected = g_value_get_uint (from);
model = gtk_drop_down_get_model (GTK_DROP_DOWN (source));
item = g_list_model_get_item (model, selected);
g_value_set_object (to, item);
g_clear_object (&item);
return TRUE;
}
GtkWidget *
create_color_grid (void)
{
GtkWidget *gridview;
GtkListItemFactory *factory;
GListModel *model, *selection;
gridview = gtk_grid_view_new ();
gtk_scrollable_set_hscroll_policy (GTK_SCROLLABLE (gridview), GTK_SCROLL_NATURAL);
gtk_scrollable_set_vscroll_policy (GTK_SCROLLABLE (gridview), GTK_SCROLL_NATURAL);
factory = gtk_signal_list_item_factory_new ();
g_signal_connect (factory, "setup", G_CALLBACK (setup_simple_listitem_cb), NULL);
gtk_grid_view_set_factory (GTK_GRID_VIEW (gridview), factory);
g_object_unref (factory);
gtk_grid_view_set_max_columns (GTK_GRID_VIEW (gridview), 24);
gtk_grid_view_set_enable_rubberband (GTK_GRID_VIEW (gridview), TRUE);
model = G_LIST_MODEL (gtk_sort_list_model_new (create_colors_model (), NULL));
selection = G_LIST_MODEL (gtk_multi_selection_new (model));
gtk_grid_view_set_model (GTK_GRID_VIEW (gridview), selection);
g_object_unref (selection);
g_object_unref (model);
return gridview;
}
static GtkWidget *window = NULL;
GtkWidget *
do_listview_colors (GtkWidget *do_widget)
{
if (window == NULL)
{
GtkWidget *header, *gridview, *sw, *box, *dropdown;
GtkListItemFactory *factory;
GListStore *factories;
GListModel *model;
GtkSorter *sorter;
GtkSorter *multi_sorter;
GListStore *sorters;
GtkExpression *expression;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
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);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_container_add (GTK_CONTAINER (window), sw);
gridview = create_color_grid ();
gtk_container_add (GTK_CONTAINER (sw), gridview);
model = gtk_grid_view_get_model (GTK_GRID_VIEW (gridview));
g_object_get (model, "model", &model, NULL);
sorters = g_list_store_new (GTK_TYPE_SORTER);
sorter = gtk_string_sorter_new (gtk_property_expression_new (GTK_TYPE_COLOR, NULL, "name"));
set_title (sorter, "Name");
g_list_store_append (sorters, sorter);
g_object_unref (sorter);
multi_sorter = gtk_multi_sorter_new ();
sorter = gtk_numeric_sorter_new (gtk_property_expression_new (GTK_TYPE_COLOR, NULL, "red"));
gtk_numeric_sorter_set_sort_order (GTK_NUMERIC_SORTER (sorter), GTK_SORT_DESCENDING);
set_title (sorter, "Red");
g_list_store_append (sorters, sorter);
gtk_multi_sorter_append (GTK_MULTI_SORTER (multi_sorter), sorter);
sorter = gtk_numeric_sorter_new (gtk_property_expression_new (GTK_TYPE_COLOR, NULL, "green"));
gtk_numeric_sorter_set_sort_order (GTK_NUMERIC_SORTER (sorter), GTK_SORT_DESCENDING);
set_title (sorter, "Green");
g_list_store_append (sorters, sorter);
gtk_multi_sorter_append (GTK_MULTI_SORTER (multi_sorter), sorter);
sorter = gtk_numeric_sorter_new (gtk_property_expression_new (GTK_TYPE_COLOR, NULL, "blue"));
gtk_numeric_sorter_set_sort_order (GTK_NUMERIC_SORTER (sorter), GTK_SORT_DESCENDING);
set_title (sorter, "Blue");
g_list_store_append (sorters, sorter);
gtk_multi_sorter_append (GTK_MULTI_SORTER (multi_sorter), sorter);
set_title (multi_sorter, "RGB");
g_list_store_append (sorters, multi_sorter);
g_object_unref (multi_sorter);
multi_sorter = gtk_multi_sorter_new ();
sorter = gtk_numeric_sorter_new (gtk_property_expression_new (GTK_TYPE_COLOR, NULL, "hue"));
gtk_numeric_sorter_set_sort_order (GTK_NUMERIC_SORTER (sorter), GTK_SORT_DESCENDING);
set_title (sorter, "Hue");
g_list_store_append (sorters, sorter);
gtk_multi_sorter_append (GTK_MULTI_SORTER (multi_sorter), sorter);
sorter = gtk_numeric_sorter_new (gtk_property_expression_new (GTK_TYPE_COLOR, NULL, "saturation"));
gtk_numeric_sorter_set_sort_order (GTK_NUMERIC_SORTER (sorter), GTK_SORT_DESCENDING);
set_title (sorter, "Saturation");
g_list_store_append (sorters, sorter);
gtk_multi_sorter_append (GTK_MULTI_SORTER (multi_sorter), sorter);
sorter = gtk_numeric_sorter_new (gtk_property_expression_new (GTK_TYPE_COLOR, NULL, "value"));
gtk_numeric_sorter_set_sort_order (GTK_NUMERIC_SORTER (sorter), GTK_SORT_DESCENDING);
set_title (sorter, "Value");
g_list_store_append (sorters, sorter);
gtk_multi_sorter_append (GTK_MULTI_SORTER (multi_sorter), sorter);
set_title (multi_sorter, "HSV");
g_list_store_append (sorters, multi_sorter);
g_object_unref (multi_sorter);
dropdown = gtk_drop_down_new ();
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
gtk_container_add (GTK_CONTAINER (box), gtk_label_new ("Sort by:"));
gtk_container_add (GTK_CONTAINER (box), dropdown);
gtk_header_bar_pack_end (GTK_HEADER_BAR (header), box);
expression = gtk_cclosure_expression_new (G_TYPE_STRING,
NULL,
0, NULL,
(GCallback)get_title,
NULL, NULL);
gtk_drop_down_set_expression (GTK_DROP_DOWN (dropdown), expression);
gtk_expression_unref (expression);
gtk_drop_down_set_model (GTK_DROP_DOWN (dropdown), G_LIST_MODEL (sorters));
g_object_unref (sorters);
g_object_bind_property_full (dropdown, "selected",
model, "sorter",
G_BINDING_SYNC_CREATE,
set_item, NULL,
NULL, NULL);
factories = g_list_store_new (GTK_TYPE_LIST_ITEM_FACTORY);
factory = gtk_signal_list_item_factory_new ();
g_signal_connect (factory, "setup", G_CALLBACK (setup_simple_listitem_cb), NULL);
set_title (factory, "Colors");
g_list_store_append (factories, factory);
factory = gtk_signal_list_item_factory_new ();
g_signal_connect (factory, "setup", G_CALLBACK (setup_listitem_cb), NULL);
set_title (factory, "Everything");
g_list_store_append (factories, factory);
dropdown = gtk_drop_down_new ();
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
gtk_container_add (GTK_CONTAINER (box), gtk_label_new ("Show:"));
gtk_container_add (GTK_CONTAINER (box), dropdown);
gtk_header_bar_pack_end (GTK_HEADER_BAR (header), box);
expression = gtk_cclosure_expression_new (G_TYPE_STRING,
NULL,
0, NULL,
(GCallback)get_title,
NULL, NULL);
gtk_drop_down_set_expression (GTK_DROP_DOWN (dropdown), expression);
gtk_expression_unref (expression);
gtk_drop_down_set_model (GTK_DROP_DOWN (dropdown), G_LIST_MODEL (factories));
g_object_unref (factories);
g_object_bind_property_full (dropdown, "selected",
gridview, "factory",
G_BINDING_SYNC_CREATE,
set_item, NULL,
NULL, NULL);
g_object_unref (model);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_widget_destroy (window);
return window;
}
+2 -1
View File
@@ -1,7 +1,8 @@
/* Lists/File browser
*
* This demo shows off the different layouts that are quickly achievable
* with GtkGridView by implementing a file browser with different views.
* with GtkListview and GtkGridView by implementing a file browser with
* different views.
*/
#include <glib/gi18n.h>
+148 -6
View File
@@ -2,7 +2,9 @@
*
* This demo shows a settings viewer for GSettings.
*
* It demonstrates how to implement support for trees with listview.
* It demonstrates how to implement support for trees with GtkListView.
*
* It also shows how to set up sorting for columns in a GtkColumnView.
*/
#include <gtk/gtk.h>
@@ -69,11 +71,23 @@ settings_key_get_property (GObject *object,
}
}
static void
settings_key_finalize (GObject *object)
{
SettingsKey *self = SETTINGS_KEY (object);
g_object_unref (self->settings);
g_settings_schema_key_unref (self->key);
G_OBJECT_CLASS (settings_key_parent_class)->finalize (object);
}
static void
settings_key_class_init (SettingsKeyClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = settings_key_finalize;
gobject_class->get_property = settings_key_get_property;
properties[PROP_DESCRIPTION] =
@@ -115,16 +129,22 @@ strvcmp (gconstpointer p1,
return strcmp (*s1, *s2);
}
static GtkFilter *current_filter;
static gboolean
transform_settings_to_keys (GBinding *binding,
const GValue *from_value,
GValue *to_value,
gpointer unused)
gpointer data)
{
GtkTreeListRow *treelistrow;
GSettings *settings;
GSettingsSchema *schema;
GListStore *store;
GtkSortListModel *sort_model;
GtkFilterListModel *filter_model;
GtkFilter *filter;
GtkExpression *expression;
char **keys;
guint i;
@@ -137,7 +157,6 @@ transform_settings_to_keys (GBinding *binding,
store = g_list_store_new (SETTINGS_TYPE_KEY);
keys = g_settings_schema_list_keys (schema);
qsort (keys, g_strv_length (keys), sizeof (char *), strvcmp);
for (i = 0; keys[i] != NULL; i++)
{
@@ -152,7 +171,21 @@ transform_settings_to_keys (GBinding *binding,
g_settings_schema_unref (schema);
g_object_unref (settings);
g_value_take_object (to_value, store);
sort_model = gtk_sort_list_model_new (G_LIST_MODEL (store),
gtk_column_view_get_sorter (GTK_COLUMN_VIEW (data)));
g_object_unref (store);
expression = gtk_property_expression_new (SETTINGS_TYPE_KEY, NULL, "name");
filter = gtk_string_filter_new ();
gtk_string_filter_set_expression (GTK_STRING_FILTER (filter), expression);
filter_model = gtk_filter_list_model_new (G_LIST_MODEL (sort_model), filter);
gtk_expression_unref (expression);
g_object_unref (sort_model);
g_set_object (&current_filter, filter);
g_object_unref (filter);
g_value_take_object (to_value, filter_model);
return TRUE;
}
@@ -200,9 +233,81 @@ create_settings_model (gpointer item,
g_object_unref (child);
}
g_strfreev (schemas);
return G_LIST_MODEL (result);
}
static void
search_enabled (GtkSearchEntry *entry)
{
gtk_editable_set_text (GTK_EDITABLE (entry), "");
}
static void
search_changed (GtkSearchEntry *entry,
gpointer data)
{
const char *text = gtk_editable_get_text (GTK_EDITABLE (entry));
if (current_filter)
gtk_string_filter_set_search (GTK_STRING_FILTER (current_filter), text);
}
static void
stop_search (GtkSearchEntry *entry,
gpointer data)
{
gtk_editable_set_text (GTK_EDITABLE (entry), "");
if (current_filter)
gtk_string_filter_set_search (GTK_STRING_FILTER (current_filter), "");
}
static void
move_column (GtkListView *columns_list, gboolean down)
{
GListModel *columns;
guint position;
GtkColumnViewColumn *selected;
GtkColumnView *view;
columns = gtk_list_view_get_model (columns_list);
position = gtk_single_selection_get_selected (GTK_SINGLE_SELECTION (columns));
selected = gtk_single_selection_get_selected_item (GTK_SINGLE_SELECTION (columns));
view = gtk_column_view_column_get_column_view (selected);
if (down && position + 1 < g_list_model_get_n_items (columns))
position++;
else if (!down && position > 0)
position--;
else
return;
gtk_column_view_insert_column (view, position, selected);
gtk_single_selection_set_selected (GTK_SINGLE_SELECTION (columns), position);
}
static void
move_column_down (GtkListView *columns_list)
{
move_column (columns_list, TRUE);
}
static void
move_column_up (GtkListView *columns_list)
{
move_column (columns_list, FALSE);
}
static void
column_visible_toggled (GtkListItem *item, GtkToggleButton *button)
{
GtkColumnViewColumn *column = gtk_list_item_get_item (item);
gtk_column_view_column_set_visible (column, gtk_toggle_button_get_active (button));
}
static GtkWidget *window = NULL;
GtkWidget *
@@ -214,11 +319,32 @@ do_listview_settings (GtkWidget *do_widget)
GListModel *model;
GtkTreeListModel *treemodel;
GtkSingleSelection *selection;
GtkBuilderScope *scope;
GtkBuilder *builder;
GtkColumnViewColumn *name_column;
GtkSorter *sorter;
GtkWidget *menubutton, *popover;
GtkWidget *columns_list;
g_type_ensure (SETTINGS_TYPE_KEY);
builder = gtk_builder_new_from_resource ("/listview_settings/listview_settings.ui");
scope = gtk_builder_cscope_new ();
gtk_builder_cscope_add_callback_symbol (GTK_BUILDER_CSCOPE (scope), "search_enabled", (GCallback)search_enabled);
gtk_builder_cscope_add_callback_symbol (GTK_BUILDER_CSCOPE (scope), "search_changed", (GCallback)search_changed);
gtk_builder_cscope_add_callback_symbol (GTK_BUILDER_CSCOPE (scope), "stop_search", (GCallback)stop_search);
gtk_builder_cscope_add_callback_symbol (GTK_BUILDER_CSCOPE (scope), "move_column_down", (GCallback)move_column_down);
gtk_builder_cscope_add_callback_symbol (GTK_BUILDER_CSCOPE (scope), "move_column_up", (GCallback)move_column_up);
gtk_builder_cscope_add_callback_symbol (GTK_BUILDER_CSCOPE (scope), "column_visible_toggled", (GCallback)column_visible_toggled);
builder = gtk_builder_new ();
gtk_builder_set_scope (builder, scope);
{
g_autoptr(GError) error = NULL;
gtk_builder_add_from_resource (builder, "/listview_settings/listview_settings.ui", &error);
if (error)
g_warning ("%s", error->message);
}
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
@@ -240,11 +366,27 @@ do_listview_settings (GtkWidget *do_widget)
G_BINDING_SYNC_CREATE,
transform_settings_to_keys,
NULL,
NULL, NULL);
columnview, NULL);
gtk_list_view_set_model (GTK_LIST_VIEW (listview), G_LIST_MODEL (selection));
g_object_unref (selection);
g_object_unref (treemodel);
g_object_unref (model);
name_column = GTK_COLUMN_VIEW_COLUMN (gtk_builder_get_object (builder, "name_column"));
sorter = gtk_string_sorter_new (gtk_property_expression_new (SETTINGS_TYPE_KEY, NULL, "name"));
gtk_column_view_column_set_sorter (name_column, sorter);
g_object_unref (sorter);
menubutton = GTK_WIDGET (gtk_builder_get_object (builder, "menubutton"));
popover = GTK_WIDGET (gtk_builder_get_object (builder, "column_popover"));
gtk_menu_button_set_popover (GTK_MENU_BUTTON (menubutton), popover);
columns_list = GTK_WIDGET (gtk_builder_get_object (builder, "columns_list"));
model = G_LIST_MODEL (gtk_single_selection_new (gtk_column_view_get_columns (GTK_COLUMN_VIEW (columnview))));
gtk_list_view_set_model (GTK_LIST_VIEW (columns_list), model);
g_object_unref (model);
g_object_unref (builder);
}
if (!gtk_widget_get_visible (window))
+173 -19
View File
@@ -2,10 +2,26 @@
<interface>
<object class="GtkWindow" id="window">
<property name="title" translatable="yes">Settings</property>
<property name="default-width">600</property>
<property name="default-height">400</property>
<property name="default-width">640</property>
<property name="default-height">480</property>
<child type="titlebar">
<object class="GtkHeaderBar">
<property name="show-title-buttons">1</property>
<child type="end">
<object class="GtkMenuButton" id="menubutton">
<property name="icon-name">open-menu-symbolic</property>
</object>
</child>
<child type="end">
<object class="GtkToggleButton" id="search_button">
<property name="icon-name">system-search-symbolic</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkPaned">
<property name="position">300</property>
<child>
<object class="GtkScrolledWindow">
<child>
@@ -43,15 +59,31 @@
</object>
</child>
<child>
<object class="GtkScrolledWindow">
<object class="GtkBox">
<property name="orientation">vertical</property>
<child>
<object class="GtkColumnView" id="columnview">
<object class="GtkSearchBar">
<property name="search-mode-enabled" bind-source="search_button" bind-property="active" bind-flags="bidirectional"/>
<signal name="notify::search-mode-enabled" handler="search_enabled" object="entry"/>
<child>
<object class="GtkColumnViewColumn">
<property name="title">Name</property>
<property name="factory">
<object class="GtkBuilderListItemFactory">
<property name="bytes"><![CDATA[
<object class="GtkSearchEntry" id="entry">
<signal name="search-changed" handler="search_changed"/>
<signal name="stop-search" handler="stop_search"/>
</object>
</child>
</object>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="expand">1</property>
<child>
<object class="GtkColumnView" id="columnview">
<child>
<object class="GtkColumnViewColumn" id="name_column">
<property name="title">Name</property>
<property name="factory">
<object class="GtkBuilderListItemFactory">
<property name="bytes"><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="GtkListItem">
@@ -68,16 +100,16 @@
</template>
</interface>
]]></property>
</object>
</property>
</object>
</property>
</object>
</child>
<child>
<object class="GtkColumnViewColumn">
<property name="title">Value</property>
<property name="factory">
<object class="GtkBuilderListItemFactory">
<property name="bytes"><![CDATA[
</child>
<child>
<object class="GtkColumnViewColumn" id="value_column">
<property name="title">Value</property>
<property name="factory">
<object class="GtkBuilderListItemFactory">
<property name="bytes"><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="GtkListItem">
@@ -94,8 +126,62 @@
</template>
</interface>
]]></property>
</object>
</property>
</object>
</property>
</child>
<child>
<object class="GtkColumnViewColumn" id="summary_column">
<property name="title">Summary</property>
<property name="factory">
<object class="GtkBuilderListItemFactory">
<property name="bytes"><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="GtkListItem">
<property name="child">
<object class="GtkLabel">
<property name="xalign">0</property>
<binding name="label">
<lookup name="summary" type="SettingsKey">
<lookup name="item">GtkListItem</lookup>
</lookup>
</binding>
</object>
</property>
</template>
</interface>
]]></property>
</object>
</property>
</object>
</child>
<child>
<object class="GtkColumnViewColumn" id="description_column">
<property name="title">Description</property>
<property name="factory">
<object class="GtkBuilderListItemFactory">
<property name="bytes"><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="GtkListItem">
<property name="child">
<object class="GtkLabel">
<property name="xalign">0</property>
<binding name="label">
<lookup name="description" type="SettingsKey">
<lookup name="item">GtkListItem</lookup>
</lookup>
</binding>
</object>
</property>
</template>
</interface>
]]></property>
</object>
</property>
</object>
</child>
</object>
</child>
</object>
@@ -105,4 +191,72 @@
</object>
</child>
</object>
<object class="GtkPopover" id="column_popover">
<child>
<object class="GtkBox">
<property name="orientation">vertical</property>
<child>
<object class="GtkListView" id="columns_list">
<property name="factory">
<object class="GtkBuilderListItemFactory">
<property name="bytes"><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="GtkListItem">
<property name="child">
<object class="GtkBox">
<property name="spacing">10</property>
<child>
<object class="GtkCheckButton">
<signal name="toggled" handler="column_visible_toggled" object="GtkListItem"/>
<binding name="active">
<lookup name="visible" type="GtkColumnViewColumn">
<lookup name="item">GtkListItem</lookup>
</lookup>
</binding>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="xalign">0</property>
<property name="label">label</property>
<binding name="label">
<lookup name="title" type="GtkColumnViewColumn">
<lookup name="item">GtkListItem</lookup>
</lookup>
</binding>
</object>
</child>
</object>
</property>
</template>
</interface>
]]></property>
</object>
</property>
</object>
</child>
<child>
<object class="GtkBox">
<property name="halign">center</property>
<style>
<class name="linked"/>
</style>
<child>
<object class="GtkButton">
<property name="icon-name">go-down-symbolic</property>
<signal name="clicked" handler="move_column_down" object="columns_list"/>
</object>
</child>
<child>
<object class="GtkButton">
<property name="icon-name">go-up-symbolic</property>
<signal name="clicked" handler="move_column_up" object="columns_list"/>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</interface>
+26 -13
View File
@@ -5,12 +5,13 @@
*
* The hourly weather info uses a horizontal listview. This is easy
* to achieve because GtkListView implements the GtkOrientable interface.
*
* To make the items in the list stand out more, the listview uses
* separators.
*
* A GtkNoSelectionModel is used to make sure no item in the list can be
* selected. All other interactions with the items is still possible.
*
* The dataset used here has 70000 items.
*/
#include <gtk/gtk.h>
@@ -274,15 +275,37 @@ bind_widget (GtkListItem *list_item,
static GtkWidget *window = NULL;
GtkWidget *
create_weather_view (void)
{
GtkWidget *listview;
GListModel *model, *selection;
listview = gtk_list_view_new_with_factory (
gtk_functions_list_item_factory_new (setup_widget,
bind_widget,
NULL, NULL));
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 ();
selection = G_LIST_MODEL (gtk_no_selection_new (model));
gtk_list_view_set_model (GTK_LIST_VIEW (listview), selection);
g_object_unref (selection);
g_object_unref (model);
return listview;
}
GtkWidget *
do_listview_weather (GtkWidget *do_widget)
{
if (window == NULL)
{
GtkWidget *listview, *sw;;
GListModel *model, *selection;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
gtk_window_set_title (GTK_WINDOW (window), "Weather");
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Weather");
@@ -292,17 +315,7 @@ do_listview_weather (GtkWidget *do_widget)
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_container_add (GTK_CONTAINER (window), sw);
listview = gtk_list_view_new_with_factory (
gtk_functions_list_item_factory_new (setup_widget,
bind_widget,
NULL, NULL));
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 ();
selection = G_LIST_MODEL (gtk_no_selection_new (model));
gtk_list_view_set_model (GTK_LIST_VIEW (listview), selection);
g_object_unref (selection);
g_object_unref (model);
listview = create_weather_view ();
gtk_container_add (GTK_CONTAINER (sw), listview);
}
+1
View File
@@ -46,6 +46,7 @@ demos = files([
'list_store.c',
'listview_applauncher.c',
'listview_clocks.c',
'listview_colors.c',
'listview_filebrowser.c',
'listview_minesweeper.c',
'listview_settings.c',
+10 -10
View File
@@ -75,11 +75,11 @@
<property name="adjustment">adjustment2</property>
<property name="hexpand">1</property>
<marks>
<mark value="0" position="bottom"/>
<mark value="1" position="bottom"/>
<mark value="2" position="bottom"/>
<mark value="3" position="bottom"/>
<mark value="4" position="bottom"/>
<mark value="0" position="bottom"></mark>
<mark value="1" position="bottom"></mark>
<mark value="2" position="bottom"></mark>
<mark value="3" position="bottom"></mark>
<mark value="4" position="bottom"></mark>
</marks>
<accessibility>
<relation type="labelled-by" target="label_marks"/>
@@ -115,11 +115,11 @@
<relation type="labelled-by" target="label_discrete"/>
</accessibility>
<marks>
<mark value="0" position="bottom"/>
<mark value="1" position="bottom"/>
<mark value="2" position="bottom"/>
<mark value="3" position="bottom"/>
<mark value="4" position="bottom"/>
<mark value="0" position="bottom"></mark>
<mark value="1" position="bottom"></mark>
<mark value="2" position="bottom"></mark>
<mark value="3" position="bottom"></mark>
<mark value="4" position="bottom"></mark>
</marks>
<layout>
<property name="left-attach">1</property>
+210 -211
View File
@@ -6,236 +6,235 @@
<object class="GtkHeaderBar" id="header">
<property name="show-title-buttons">1</property>
<child type="end">
<object class="GtkLabel" id="fps">
</object>
<object class="GtkLabel" id="fps"/>
</child>
</object>
</child>
<child>
<object class="GtkGrid" id="grid">
<property name="margin">10</property>
<property name="row-spacing">10</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkToolbar">
<property name="hexpand">1</property>
<property name="show-arrow">0</property>
<style>
<class name="primary-toolbar"/>
</style>
<object class="GtkGrid" id="grid">
<property name="margin">10</property>
<property name="row-spacing">10</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="label" translatable="yes">Normal</property>
<property name="use-underline">1</property>
<property name="is-important">1</property>
<property name="icon-name">edit-find</property>
</object>
</child>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="label" translatable="yes">Active</property>
<property name="use-underline">1</property>
<property name="is-important">1</property>
<property name="icon-name">edit-find</property>
<property name="active">1</property>
</object>
</child>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="sensitive">0</property>
<property name="label" translatable="yes">Insensitive</property>
<property name="use-underline">1</property>
<property name="is-important">1</property>
<property name="icon-name">edit-find</property>
</object>
</child>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="label" translatable="yes">Raised</property>
<property name="use-underline">1</property>
<property name="is-important">1</property>
<property name="icon-name">edit-find</property>
<style>
<class name="raised"/>
</style>
</object>
</child>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="label" translatable="yes">Raised Active</property>
<property name="use-underline">1</property>
<property name="is-important">1</property>
<property name="icon-name">edit-find</property>
<property name="active">1</property>
<style>
<class name="raised"/>
</style>
</object>
</child>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="sensitive">0</property>
<property name="label" translatable="yes">Insensitive Active</property>
<property name="use-underline">1</property>
<property name="icon-name">edit-find</property>
<property name="is-important">1</property>
<property name="active">1</property>
</object>
</child>
<child>
<object class="GtkToolItem">
<child>
<object class="GtkEntry" id="entry1">
<property name="can-focus">1</property>
<property name="width-chars">10</property>
<property name="invisible-char">•</property>
<property name="placeholder-text" translatable="yes">Search...</property>
<property name="secondary-icon-name">edit-find-symbolic</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkToolItem">
<child>
<object class="GtkSwitch" id="switch1">
<property name="can-focus">1</property>
<property name="valign">center</property>
<property name="tooltip_text">Switch it</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox">
<property name="valign">center</property>
<property name="halign">center</property>
<style>
<class name="linked"/>
</style>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">Hi, I am a button</property>
<property name="can-focus">1</property>
<property name="receives-default">1</property>
</object>
</child>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">And I&apos;m another button</property>
<property name="can-focus">1</property>
<property name="receives-default">1</property>
</object>
</child>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">This is a button party!</property>
<property name="can-focus">1</property>
<property name="receives-default">1</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkToolbar">
<property name="hexpand">1</property>
<property name="toolbar-style">icons</property>
<style>
<class name="inline-toolbar"/>
</style>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="label" translatable="yes">Normal</property>
<property name="use-underline">1</property>
<property name="icon-name">list-add-symbolic</property>
</object>
</child>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="label" translatable="yes">Normal</property>
<property name="use-underline">1</property>
<property name="icon-name">list-add-symbolic</property>
</object>
</child>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="label" translatable="yes">Active</property>
<property name="use-underline">1</property>
<property name="icon-name">list-remove-symbolic</property>
<property name="active">1</property>
</object>
</child>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="label" translatable="yes">Active</property>
<property name="use-underline">1</property>
<property name="icon-name">list-remove-symbolic</property>
<property name="active">1</property>
</object>
</child>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="sensitive">0</property>
<property name="label" translatable="yes">Insensitive</property>
<property name="use-underline">1</property>
<property name="icon-name">edit-find-symbolic</property>
</object>
</child>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="sensitive">0</property>
<property name="label" translatable="yes">Insensitive Active</property>
<property name="use-underline">1</property>
<property name="icon-name">go-up-symbolic</property>
<property name="active">1</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox">
<property name="spacing">10</property>
<child>
<object class="GtkButton">
<property name="label">Plain</property>
<property name="halign">end</property>
<object class="GtkToolbar">
<property name="hexpand">1</property>
<property name="vexpand">1</property>
<property name="show-arrow">0</property>
<style>
<class name="primary-toolbar"/>
</style>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="label" translatable="yes">Normal</property>
<property name="use-underline">1</property>
<property name="is-important">1</property>
<property name="icon-name">edit-find</property>
</object>
</child>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="label" translatable="yes">Active</property>
<property name="use-underline">1</property>
<property name="is-important">1</property>
<property name="icon-name">edit-find</property>
<property name="active">1</property>
</object>
</child>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="sensitive">0</property>
<property name="label" translatable="yes">Insensitive</property>
<property name="use-underline">1</property>
<property name="is-important">1</property>
<property name="icon-name">edit-find</property>
</object>
</child>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="label" translatable="yes">Raised</property>
<property name="use-underline">1</property>
<property name="is-important">1</property>
<property name="icon-name">edit-find</property>
<style>
<class name="raised"/>
</style>
</object>
</child>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="label" translatable="yes">Raised Active</property>
<property name="use-underline">1</property>
<property name="is-important">1</property>
<property name="icon-name">edit-find</property>
<property name="active">1</property>
<style>
<class name="raised"/>
</style>
</object>
</child>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="sensitive">0</property>
<property name="label" translatable="yes">Insensitive Active</property>
<property name="use-underline">1</property>
<property name="icon-name">edit-find</property>
<property name="is-important">1</property>
<property name="active">1</property>
</object>
</child>
<child>
<object class="GtkToolItem">
<child>
<object class="GtkEntry" id="entry1">
<property name="can-focus">1</property>
<property name="width-chars">10</property>
<property name="invisible-char">•</property>
<property name="placeholder-text" translatable="yes">Search...</property>
<property name="secondary-icon-name">edit-find-symbolic</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkToolItem">
<child>
<object class="GtkSwitch" id="switch1">
<property name="can-focus">1</property>
<property name="valign">center</property>
<property name="tooltip_text">Switch it</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkButton">
<property name="label">Destructive</property>
<object class="GtkBox">
<property name="valign">center</property>
<property name="halign">center</property>
<style>
<class name="destructive-action"/>
<class name="linked"/>
</style>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">Hi, I am a button</property>
<property name="can-focus">1</property>
<property name="receives-default">1</property>
</object>
</child>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">And I&apos;m another button</property>
<property name="can-focus">1</property>
<property name="receives-default">1</property>
</object>
</child>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">This is a button party!</property>
<property name="can-focus">1</property>
<property name="receives-default">1</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkButton">
<property name="label">Suggested</property>
<object class="GtkToolbar">
<property name="hexpand">1</property>
<property name="toolbar-style">icons</property>
<style>
<class name="suggested-action"/>
<class name="inline-toolbar"/>
</style>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="label" translatable="yes">Normal</property>
<property name="use-underline">1</property>
<property name="icon-name">list-add-symbolic</property>
</object>
</child>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="label" translatable="yes">Normal</property>
<property name="use-underline">1</property>
<property name="icon-name">list-add-symbolic</property>
</object>
</child>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="label" translatable="yes">Active</property>
<property name="use-underline">1</property>
<property name="icon-name">list-remove-symbolic</property>
<property name="active">1</property>
</object>
</child>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="label" translatable="yes">Active</property>
<property name="use-underline">1</property>
<property name="icon-name">list-remove-symbolic</property>
<property name="active">1</property>
</object>
</child>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="sensitive">0</property>
<property name="label" translatable="yes">Insensitive</property>
<property name="use-underline">1</property>
<property name="icon-name">edit-find-symbolic</property>
</object>
</child>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="sensitive">0</property>
<property name="label" translatable="yes">Insensitive Active</property>
<property name="use-underline">1</property>
<property name="icon-name">go-up-symbolic</property>
<property name="active">1</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox">
<property name="spacing">10</property>
<child>
<object class="GtkButton">
<property name="label">Plain</property>
<property name="halign">end</property>
<property name="hexpand">1</property>
<property name="vexpand">1</property>
</object>
</child>
<child>
<object class="GtkButton">
<property name="label">Destructive</property>
<style>
<class name="destructive-action"/>
</style>
</object>
</child>
<child>
<object class="GtkButton">
<property name="label">Suggested</property>
<style>
<class name="suggested-action"/>
</style>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</interface>
+2
View File
@@ -2,6 +2,7 @@
<interface>
<object class="GtkGrid" id="grid">
<property name="row-spacing">10</property>
<property name="margin">10</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkToolbar">
@@ -92,6 +93,7 @@
<child>
<object class="GtkSwitch" id="switch1">
<property name="can-focus">1</property>
<property name="valign">center</property>
<property name="tooltip_text">Switch it</property>
</object>
</child>
+52 -44
View File
@@ -3198,6 +3198,10 @@ bad things might happen.</property>
<style>
<class name="dim-label"/>
</style>
<layout>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
</layout>
</object>
</child>
<child>
@@ -3205,6 +3209,7 @@ bad things might happen.</property>
<property name="valign">baseline</property>
<layout>
<property name="left-attach">1</property>
<property name="top-attach">0</property>
</layout>
</object>
</child>
@@ -3219,6 +3224,7 @@ bad things might happen.</property>
<class name="dim-label"/>
</style>
<layout>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</layout>
</object>
@@ -3243,6 +3249,7 @@ bad things might happen.</property>
<class name="dim-label"/>
</style>
<layout>
<property name="left-attach">0</property>
<property name="top-attach">2</property>
</layout>
</object>
@@ -3269,6 +3276,7 @@ bad things might happen.</property>
<class name="dim-label"/>
</style>
<layout>
<property name="left-attach">0</property>
<property name="top-attach">3</property>
</layout>
</object>
@@ -3684,50 +3692,50 @@ bad things might happen.</property>
</child>
<child>
<object class="GtkStackPage">
<property name="name">basement</property>
<property name="child">
<object class="GtkBox">
<property name="orientation">vertical</property>
<child>
<object class="GtkModelButton">
<property name="text">Basement</property>
<property name="role">title</property>
<property name="menu-name">main</property>
</object>
</child>
<child>
<object class="GtkSeparator"/>
</child>
<child>
<object class="GtkModelButton">
<property name="text">Berk</property>
<property name="action-name">app.berk</property>
<property name="indicator-size-group">basement-indicators</property>
</object>
</child>
<child>
<object class="GtkModelButton">
<property name="text">Broni</property>
<property name="action-name">app.broni</property>
<property name="indicator-size-group">basement-indicators</property>
</object>
</child>
<child>
<object class="GtkModelButton">
<property name="text">Drutt</property>
<property name="action-name">app.drutt</property>
<property name="indicator-size-group">basement-indicators</property>
</object>
</child>
<child>
<object class="GtkModelButton">
<property name="text">The Thing Upstairs</property>
<property name="action-name">app.upstairs</property>
<property name="indicator-size-group">basement-indicators</property>
</object>
</child>
</object>
</property>
<property name="name">basement</property>
<property name="child">
<object class="GtkBox">
<property name="orientation">vertical</property>
<child>
<object class="GtkModelButton">
<property name="text">Basement</property>
<property name="role">title</property>
<property name="menu-name">main</property>
</object>
</child>
<child>
<object class="GtkSeparator"/>
</child>
<child>
<object class="GtkModelButton">
<property name="text">Berk</property>
<property name="action-name">app.berk</property>
<property name="indicator-size-group">basement-indicators</property>
</object>
</child>
<child>
<object class="GtkModelButton">
<property name="text">Broni</property>
<property name="action-name">app.broni</property>
<property name="indicator-size-group">basement-indicators</property>
</object>
</child>
<child>
<object class="GtkModelButton">
<property name="text">Drutt</property>
<property name="action-name">app.drutt</property>
<property name="indicator-size-group">basement-indicators</property>
</object>
</child>
<child>
<object class="GtkModelButton">
<property name="text">The Thing Upstairs</property>
<property name="action-name">app.upstairs</property>
<property name="indicator-size-group">basement-indicators</property>
</object>
</child>
</object>
</property>
</object>
</child>
</object>
+39 -12
View File
@@ -44,25 +44,53 @@
<chapter id="Lists">
<title>GListModel support</title>
<xi:include href="xml/gtkfilter.xml" />
<xi:include href="xml/gtkexpression.xml" />
<xi:include href="xml/gtkfilterlistmodel.xml" />
<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" />
</section>
<xi:include href="xml/gtkflattenlistmodel.xml" />
<xi:include href="xml/gtkmaplistmodel.xml" />
<xi:include href="xml/gtkslicelistmodel.xml" />
<xi:include href="xml/gtksorter.xml" />
<xi:include href="xml/gtkstringsorter.xml" />
<xi:include href="xml/gtknumericsorter.xml" />
<xi:include href="xml/gtkcustomsorter.xml" />
<xi:include href="xml/gtkmultisorter.xml" />
<xi:include href="xml/gtktreelistrowsorter.xml" />
<xi:include href="xml/gtksortlistmodel.xml" />
<xi:include href="xml/gtktreelistmodel.xml" />
<section>
<xi:include href="xml/gtksorter.xml" />
<xi:include href="xml/gtkcustomsorter.xml" />
<xi:include href="xml/gtkstringsorter.xml" />
<xi:include href="xml/gtknumericsorter.xml" />
<xi:include href="xml/gtkmultisorter.xml" />
</section>
<xi:include href="xml/gtkselectionmodel.xml" />
<xi:include href="xml/gtknoselection.xml" />
<xi:include href="xml/gtksingleselection.xml" />
<xi:include href="xml/gtkdirectorylist.xml" />
</chapter>
<chapter id="ListContainers">
<title>List-based Widgets</title>
<xi:include href="xml/gtklistitem.xml" />
<xi:include href="xml/gtklistitemfactory.xml" />
<section>
<xi:include href="xml/gtksignallistitemfactory.xml" />
<xi:include href="xml/gtkbuilderlistitemfactory.xml" />
</section>
<xi:include href="xml/gtklistview.xml" />
<xi:include href="xml/gtkgridview.xml" />
<xi:include href="xml/gtkcolumnview.xml" />
<xi:include href="xml/gtkcolumnviewcolumn.xml" />
<xi:include href="xml/gtkdropdown.xml" />
</chapter>
<chapter id="Trees">
<xi:include href="xml/gtktreelistrow.xml" />
<xi:include href="xml/gtktreelistmodel.xml" />
<xi:include href="xml/gtktreelistrowsorter.xml" />
<xi:include href="xml/gtktreeexpander.xml" />
</chapter>
<chapter id="Application">
<title>Application support</title>
<xi:include href="xml/gtkapplication.xml" />
@@ -74,11 +102,13 @@
<title>Interface builder</title>
<xi:include href="xml/gtkbuilder.xml" />
<xi:include href="xml/gtkbuildable.xml" />
<xi:include href="xml/gtkbuilderscope.xml" />
</chapter>
<chapter id="WindowWidgets">
<title>Windows</title>
<xi:include href="xml/gtkroot.xml" />
<xi:include href="xml/gtknative.xml" />
<xi:include href="xml/gtkwindow.xml" />
<xi:include href="xml/gtkdialog.xml" />
<xi:include href="xml/gtkmessagedialog.xml" />
@@ -95,10 +125,6 @@
<xi:include href="xml/gtkrevealer.xml" />
<xi:include href="xml/gtklistbox.xml" />
<xi:include href="xml/gtkflowbox.xml" />
<xi:include href="xml/gtksignallistitemfactory.xml" />
<xi:include href="xml/gtklistview.xml" />
<xi:include href="xml/gtkgridview.xml" />
<xi:include href="xml/gtktreeexpander.xml" />
<xi:include href="xml/gtkstack.xml" />
<xi:include href="xml/gtkstackswitcher.xml" />
<xi:include href="xml/gtkstacksidebar.xml" />
@@ -240,6 +266,7 @@
<xi:include href="xml/gtkpopover.xml" />
<xi:include href="xml/gtkpopovermenu.xml" />
<xi:include href="xml/gtkpopovermenubar.xml" />
<xi:include href="xml/gtkdropdown.xml" />
</chapter>
<chapter id="SelectorWidgets">
+202 -65
View File
@@ -213,7 +213,6 @@ gtk_adjustment_get_type
<TITLE>GtkAssistant</TITLE>
GtkAssistant
GtkAssistantPage
GtkAssistantClass
gtk_assistant_new
gtk_assistant_get_page
gtk_assistant_get_pages
@@ -258,7 +257,6 @@ gtk_assistant_get_type
<FILE>gtkaspectframe</FILE>
<TITLE>GtkAspectFrame</TITLE>
GtkAspectFrame
GtkAspectFrameClass
gtk_aspect_frame_new
gtk_aspect_frame_set
<SUBSECTION Standard>
@@ -369,7 +367,6 @@ gtk_center_layout_get_type
<FILE>gtklistbox</FILE>
<TITLE>GtkListBox</TITLE>
GtkListBox
GtkListBoxClass
GtkListBoxRow
GtkListBoxRowClass
GtkListBoxFilterFunc
@@ -515,6 +512,41 @@ GTK_TYPE_LIST_ITEM
gtk_list_item_get_type
</SECTION>
<SECTION>
<FILE>gtklistitemfactory</FILE>
<TITLE>GtkListItemFactory</TITLE>
GtkListItemFactory
<SUBSECTION Standard>
GTK_LIST_ITEM_FACTORY
GTK_LIST_ITEM_FACTORY_CLASS
GTK_LIST_ITEM_FACTORY_GET_CLASS
GTK_IS_LIST_ITEM_FACTORY
GTK_IS_LIST_ITEM_FACTORY_CLASS
GTK_TYPE_LIST_ITEM_FACTORY
<SUBSECTION Private>
gtk_list_item_factory_get_type
</SECTION>
<SECTION>
<FILE>gtkbuilderlistitemfactory</FILE>
<TITLE>GtkBuilderListItemFactory</TITLE>
GtkBuilderListItemFactory
gtk_builder_list_item_factory_new_from_bytes
gtk_builder_list_item_factory_new_from_resource
gtk_builder_list_item_factory_get_bytes
gtk_builder_list_item_factory_get_resource
gtk_builder_list_item_factory_get_scope
<SUBSECTION Standard>
GTK_BUILDER_LIST_ITEM_FACTORY
GTK_BUILDER_LIST_ITEM_FACTORY_CLASS
GTK_BUILDER_LIST_ITEM_FACTORY_GET_CLASS
GTK_IS_BUILDER_LIST_ITEM_FACTORY
GTK_IS_BUILDER_LIST_ITEM_FACTORY_CLASS
GTK_TYPE_BUILDER_LIST_ITEM_FACTORY
<SUBSECTION Private>
gtk_builder_list_item_factory_get_type
</SECTION>
<SECTION>
<FILE>gtksignallistitemfactory</FILE>
<TITLE>GtkSignalListItemFactory</TITLE>
@@ -543,6 +575,10 @@ gtk_list_view_set_model
gtk_list_view_get_model
gtk_list_view_set_show_separators
gtk_list_view_get_show_separators
gtk_list_view_set_single_click_activate
gtk_list_view_get_single_click_activate
gtk_list_view_set_enable_rubberband
gtk_list_view_get_enable_rubberband
<SUBSECTION Standard>
GTK_LIST_VIEW
GTK_LIST_VIEW_CLASS
@@ -559,12 +595,19 @@ gtk_list_view_get_type
<TITLE>GtkColumnView</TITLE>
GtkColumnView
gtk_column_view_new
gtk_column_view_append_column
gtk_column_view_insert_column
gtk_column_view_remove_column
gtk_column_view_get_columns
gtk_column_view_get_model
gtk_column_view_set_model
gtk_column_view_get_sorter
gtk_column_view_get_show_separators
gtk_column_view_set_show_separators
gtk_column_view_set_single_click_activate
gtk_column_view_get_single_click_activate
gtk_column_view_set_enable_rubberband
gtk_column_view_get_enable_rubberband
gtk_column_view_sort_by_column
<SUBSECTION Standard>
GTK_COLUMN_VIEW
@@ -590,6 +633,10 @@ gtk_column_view_column_set_title
gtk_column_view_column_get_title
gtk_column_view_column_set_sorter
gtk_column_view_column_get_sorter
gtk_column_view_column_set_visible
gtk_column_view_column_get_visible
gtk_column_view_column_set_fixed_width
gtk_column_view_column_get_fixed_width
<SUBSECTION Standard>
GTK_COLUMN_VIEW_COLUMN
GTK_COLUMN_VIEW_COLUMN_CLASS
@@ -612,6 +659,10 @@ gtk_grid_view_set_max_columns
gtk_grid_view_get_max_columns
gtk_grid_view_set_min_columns
gtk_grid_view_get_min_columns
gtk_grid_view_set_single_click_activate
gtk_grid_view_get_single_click_activate
gtk_grid_view_set_enable_rubberband
gtk_grid_view_get_enable_rubberband
<SUBSECTION Standard>
GTK_GRID_VIEW
GTK_GRID_VIEW_CLASS
@@ -1262,7 +1313,6 @@ gtk_entry_completion_get_type
<FILE>gtkexpander</FILE>
<TITLE>GtkExpander</TITLE>
GtkExpander
GtkExpanderClass
gtk_expander_new
gtk_expander_new_with_mnemonic
gtk_expander_set_expanded
@@ -1409,7 +1459,6 @@ GtkFileChooserDialogPrivate
<FILE>gtkfilechooserwidget</FILE>
<TITLE>GtkFileChooserWidget</TITLE>
GtkFileChooserWidget
GtkFileChooserWidgetClass
gtk_file_chooser_widget_new
<SUBSECTION Standard>
GTK_FILE_CHOOSER_WIDGET
@@ -1427,7 +1476,6 @@ GtkFileChooserWidgetPrivate
<FILE>gtkfilechooserbutton</FILE>
<TITLE>GtkFileChooserButton</TITLE>
GtkFileChooserButton
GtkFileChooserButtonClass
gtk_file_chooser_button_new
gtk_file_chooser_button_new_with_dialog
gtk_file_chooser_button_get_title
@@ -1506,6 +1554,7 @@ GtkFilter
gtk_filter_match
gtk_filter_get_strictness
<SUBSECTION>
GtkFilterChange
gtk_filter_changed
<SUBSECTION>
gtk_custom_filter_new
@@ -1520,6 +1569,46 @@ GTK_FILTER_GET_CLASS
gtk_filter_get_type
</SECTION>
<SECTION>
<FILE>gtkcustomfilter</FILE>
<TITLE>GtkCustomFilter</TITLE>
GtkCustomFilter
GtkCustomFilterFunc
gtk_custom_filter_new
<SUBSECTION Standard>
GTK_CUSTOM_FILTER
GTK_IS_CUSTOM_FILTER
GTK_TYPE_CUSTOM_FILTER
GTK_CUSTOM_FILTER_CLASS
GTK_IS_CUSTOM_FILTER_CLASS
GTK_CUSTOM_FILTER_GET_CLASS
<SUBSECTION Private>
gtk_custom_filter_get_type
</SECTION>
<SECTION>
<FILE>gtkmultifilter</FILE>
<TITLE>GtkMultiFilter</TITLE>
GtkMultiFilter
gtk_multi_filter_append
gtk_multi_filter_remove
<SUBSECTION>
GtkAnyFilter
gtk_any_filter_new
<SUBSECTION>
GtkEveryFilter
gtk_every_filter_new
<SUBSECTION Standard>
GTK_CUSTOM_FILTER
GTK_IS_CUSTOM_FILTER
GTK_TYPE_CUSTOM_FILTER
GTK_CUSTOM_FILTER_CLASS
GTK_IS_CUSTOM_FILTER_CLASS
GTK_CUSTOM_FILTER_GET_CLASS
<SUBSECTION Private>
gtk_custom_filter_get_type
</SECTION>
<SECTION>
<FILE>gtkfilterlistmodel</FILE>
<TITLE>GtkFilterListModel</TITLE>
@@ -1647,7 +1736,6 @@ gtk_font_chooser_get_type
<FILE>gtkfontchooserwidget</FILE>
<TITLE>GtkFontChooserWidget</TITLE>
GtkFontChooserWidget
GtkFontChooserWidgetClass
gtk_font_chooser_widget_new
<SUBSECTION Standard>
@@ -1667,7 +1755,6 @@ gtk_font_chooser_widget_get_type
<FILE>gtkfontchooserdialog</FILE>
<TITLE>GtkFontChooserDialog</TITLE>
GtkFontChooserDialog
GtkFontChooserDialogClass
gtk_font_chooser_dialog_new
<SUBSECTION Standard>
@@ -1972,7 +2059,6 @@ GtkLabelSelectionInfo
<FILE>gtklinkbutton</FILE>
<TITLE>GtkLinkButton</TITLE>
GtkLinkButton
GtkLinkButtonClass
gtk_link_button_new
gtk_link_button_new_with_label
gtk_link_button_get_uri
@@ -2020,7 +2106,6 @@ GtkMenu
gtk_menu_new
gtk_menu_new_from_model
GtkPopoverMenuFlags
gtk_menu_new_from_model_full
gtk_menu_reorder_child
gtk_menu_popup_at_rect
gtk_menu_popup_at_widget
@@ -2524,8 +2609,6 @@ gtk_recent_manager_move_item
gtk_recent_manager_get_items
gtk_recent_manager_purge_items
<SUBSECTION>
gtk_recent_info_ref
gtk_recent_info_unref
gtk_recent_info_get_uri
gtk_recent_info_get_display_name
gtk_recent_info_get_description
@@ -2667,7 +2750,6 @@ gtk_scrollbar_get_type
<FILE>gtkscrolledwindow</FILE>
<TITLE>GtkScrolledWindow</TITLE>
GtkScrolledWindow
GtkScrolledWindowClass
gtk_scrolled_window_new
gtk_scrolled_window_get_hadjustment
gtk_scrolled_window_set_hadjustment
@@ -2719,7 +2801,6 @@ GtkScrolledWindowPrivate
<FILE>gtksearchbar</FILE>
<TITLE>GtkSearchBar</TITLE>
GtkSearchBar
GtkSearchBarClass
gtk_search_bar_new
gtk_search_bar_connect_entry
gtk_search_bar_get_search_mode
@@ -2778,7 +2859,6 @@ GtkSeparatorPrivate
<FILE>gtkseparatormenuitem</FILE>
<TITLE>GtkSeparatorMenuItem</TITLE>
GtkSeparatorMenuItem
GtkSeparatorMenuItemClass
gtk_separator_menu_item_new
<SUBSECTION Standard>
GTK_SEPARATOR_MENU_ITEM
@@ -2863,8 +2943,10 @@ gtk_slice_list_model_get_type
<FILE>gtksorter</FILE>
<TITLE>GtkSorter</TITLE>
GtkSorter
GtkSorterOrder
GtkSorterChange
gtk_sorter_compare
gtk_sorter_get_order
gtk_sorter_changed
<SUBSECTION Standard>
GTK_SORTER
@@ -2903,8 +2985,8 @@ GtkNumericSorter
gtk_numeric_sorter_new
gtk_numeric_sorter_get_expression
gtk_numeric_sorter_set_expression
gtk_numeric_sorter_get_sort_increasing
gtk_numeric_sorter_set_sort_increasing
gtk_numeric_sorter_get_sort_order
gtk_numeric_sorter_set_sort_order
<SUBSECTION Standard>
GTK_NUMERIC_SORTER
GTK_IS_NUMERIC_SORTER
@@ -3391,8 +3473,6 @@ gtk_text_view_get_iter_at_location
gtk_text_view_get_iter_at_position
gtk_text_view_buffer_to_window_coords
gtk_text_view_window_to_buffer_coords
gtk_text_view_set_border_window_size
gtk_text_view_get_border_window_size
gtk_text_view_forward_display_line
gtk_text_view_backward_display_line
gtk_text_view_forward_display_line_end
@@ -3595,7 +3675,6 @@ GtkToolItemPrivate
<FILE>gtkseparatortoolitem</FILE>
<TITLE>GtkSeparatorToolItem</TITLE>
GtkSeparatorToolItem
GtkSeparatorToolItemClass
gtk_separator_tool_item_new
gtk_separator_tool_item_set_draw
gtk_separator_tool_item_get_draw
@@ -3647,7 +3726,6 @@ GtkToolButtonPrivate
<FILE>gtkmenutoolbutton</FILE>
<TITLE>GtkMenuToolButton</TITLE>
GtkMenuToolButton
GtkMenuToolButtonClass
gtk_menu_tool_button_new
gtk_menu_tool_button_set_menu
gtk_menu_tool_button_get_menu
@@ -3729,6 +3807,29 @@ GTK_TOOLTIP
gtk_tooltip_get_type
</SECTION>
<SECTION>
<FILE>gtktreelistrow</FILE>
<TITLE>GtkTreeListRow</TITLE>
gtk_tree_list_row_get_item
gtk_tree_list_row_set_expanded
gtk_tree_list_row_get_expanded
gtk_tree_list_row_is_expandable
gtk_tree_list_row_get_position
gtk_tree_list_row_get_depth
gtk_tree_list_row_get_children
gtk_tree_list_row_get_parent
gtk_tree_list_row_get_child_row
<SUBSECTION Standard>
GTK_TREE_LIST_ROW
GTK_IS_TREE_LIST_ROW
GTK_TYPE_TREE_LIST_ROW
GTK_TREE_LIST_ROW_CLASS
GTK_IS_TREE_LIST_ROW_CLASS
GTK_TREE_LIST_ROW_GET_CLASS
<SUBSECTION Private>
gtk_tree_list_row_get_type
</SECTION>
<SECTION>
<FILE>gtktreelistmodel</FILE>
<TITLE>GtkTreeListModel</TITLE>
@@ -3742,18 +3843,6 @@ gtk_tree_list_model_set_autoexpand
gtk_tree_list_model_get_autoexpand
gtk_tree_list_model_get_child_row
gtk_tree_list_model_get_row
<SUBSECTION>
gtk_tree_list_row_get_item
gtk_tree_list_row_set_expanded
gtk_tree_list_row_get_expanded
gtk_tree_list_row_is_expandable
gtk_tree_list_row_get_position
gtk_tree_list_row_get_depth
gtk_tree_list_row_get_children
gtk_tree_list_row_get_parent
gtk_tree_list_row_get_child_row
<SUBSECTION Standard>
GTK_TREE_LIST_MODEL
GTK_IS_TREE_LIST_MODEL
@@ -3761,14 +3850,7 @@ GTK_TYPE_TREE_LIST_MODEL
GTK_TREE_LIST_MODEL_CLASS
GTK_IS_TREE_LIST_MODEL_CLASS
GTK_TREE_LIST_MODEL_GET_CLASS
GTK_TREE_LIST_ROW
GTK_IS_TREE_LIST_ROW
GTK_TYPE_TREE_LIST_ROW
GTK_TREE_LIST_ROW_CLASS
GTK_IS_TREE_LIST_ROW_CLASS
GTK_TREE_LIST_ROW_GET_CLASS
<SUBSECTION Private>
gtk_tree_list_model_get_type
gtk_tree_list_row_get_type
</SECTION>
@@ -3934,7 +4016,6 @@ gtk_tree_model_filter_get_type
<FILE>gtktreeselection</FILE>
<TITLE>GtkTreeSelection</TITLE>
GtkTreeSelection
GtkTreeSelectionClass
GtkTreeSelectionFunc
GtkTreeSelectionForeachFunc
gtk_tree_selection_set_mode
@@ -4136,7 +4217,6 @@ gtk_tree_view_column_get_type
<TITLE>GtkTreeView</TITLE>
GtkTreeView
GtkTreeViewDropPosition
GtkTreeViewPrivate
GtkTreeViewColumnDropFunc
GtkTreeViewMappingFunc
GtkTreeViewSearchEqualFunc
@@ -4252,7 +4332,6 @@ gtk_tree_view_get_type
<FILE>gtkcellview</FILE>
<TITLE>GtkCellView</TITLE>
GtkCellView
GtkCellViewClass
gtk_cell_view_new
gtk_cell_view_new_with_context
gtk_cell_view_new_with_text
@@ -4400,7 +4479,6 @@ GtkCellAreaContextPrivate
<FILE>gtkcellareabox</FILE>
<TITLE>GtkCellAreaBox</TITLE>
GtkCellAreaBox
GtkCellAreaBoxClass
gtk_cell_area_box_new
gtk_cell_area_box_pack_start
gtk_cell_area_box_pack_end
@@ -4680,7 +4758,6 @@ gtk_list_store_get_type
<FILE>gtkviewport</FILE>
<TITLE>GtkViewport</TITLE>
GtkViewport
GtkViewportClass
gtk_viewport_new
gtk_viewport_set_shadow_type
gtk_viewport_get_shadow_type
@@ -5567,9 +5644,6 @@ gtk_drag_source_add_uri_targets
<FILE>gtkbindings</FILE>
<TITLE>Bindings</TITLE>
GtkBindingSet
GtkBindingEntry
GtkBindingSignal
GtkBindingArg
gtk_binding_set_new
gtk_binding_set_by_class
gtk_binding_set_find
@@ -5594,6 +5668,8 @@ GtkDeleteType
GtkDirectionType
GtkJustification
GtkMovementStep
GtkOrdering
gtk_ordering_from_cmpfunc
GtkOrientation
GtkPackType
GtkPositionType
@@ -5614,7 +5690,6 @@ GtkIconSize
<TITLE>GtkIconTheme</TITLE>
GtkIconInfo
GtkIconTheme
GtkIconThemeClass
GtkIconLookupFlags
GTK_ICON_THEME_ERROR
GtkIconThemeError
@@ -5644,7 +5719,6 @@ gtk_icon_info_get_base_size
gtk_icon_info_get_base_scale
gtk_icon_info_get_filename
gtk_icon_info_load_icon
gtk_icon_info_load_texture
gtk_icon_info_load_icon_async
gtk_icon_info_load_icon_finish
gtk_icon_info_load_symbolic
@@ -6148,7 +6222,6 @@ gtk_print_job_get_type
<FILE>gtkpagesetupunixdialog</FILE>
<TITLE>GtkPageSetupUnixDialog</TITLE>
GtkPageSetupUnixDialog
GtkPageSetupUnixDialogClass
gtk_page_setup_unix_dialog_new
gtk_page_setup_unix_dialog_set_page_setup
gtk_page_setup_unix_dialog_get_page_setup
@@ -6359,7 +6432,6 @@ gtk_grid_get_type
<SECTION>
<FILE>gtkswitch</FILE>
GtkSwitch
GtkSwitchClass
gtk_switch_new
gtk_switch_set_active
gtk_switch_get_active
@@ -6409,7 +6481,6 @@ GTK_IS_APP_CHOOSER_ONLINE_PK_CLASS
<FILE>gtkappchooserbutton</FILE>
<TITLE>GtkAppChooserButton</TITLE>
GtkAppChooserButton
GtkAppChooserButtonClass
gtk_app_chooser_button_new
gtk_app_chooser_button_append_custom_item
gtk_app_chooser_button_append_separator
@@ -6438,7 +6509,6 @@ gtk_app_chooser_button_get_type
<FILE>gtkappchooserdialog</FILE>
<TITLE>GtkAppChooserDialog</TITLE>
GtkAppChooserDialog
GtkAppChooserDialogClass
gtk_app_chooser_dialog_new
gtk_app_chooser_dialog_new_for_content_type
gtk_app_chooser_dialog_get_widget
@@ -6462,7 +6532,6 @@ gtk_app_chooser_dialog_get_type
<FILE>gtkappchooserwidget</FILE>
<TITLE>GtkAppChooserWidget</TITLE>
GtkAppChooserWidget
GtkAppChooserWidgetClass
gtk_app_chooser_widget_new
gtk_app_chooser_widget_set_show_default
gtk_app_chooser_widget_get_show_default
@@ -6494,7 +6563,6 @@ gtk_app_chooser_widget_get_type
<FILE>gtklockbutton</FILE>
<TITLE>GtkLockButton</TITLE>
GtkLockButton
GtkLockButtonClass
gtk_lock_button_new
gtk_lock_button_get_permission
@@ -6516,7 +6584,6 @@ GtkLockButtonPrivate
<FILE>gtkoverlay</FILE>
<TITLE>GtkOverlay</TITLE>
GtkOverlay
GtkOverlayClass
gtk_overlay_new
gtk_overlay_add_overlay
@@ -6566,7 +6633,6 @@ gtk_color_chooser_get_type
<FILE>gtkcolorchooserwidget</FILE>
<TITLE>GtkColorChooserWidget</TITLE>
GtkColorChooserWidget
GtkColorChooserWidgetClass
gtk_color_chooser_widget_new
<SUBSECTION Standard>
@@ -6726,7 +6792,6 @@ gtk_stack_switcher_get_type
<FILE>gtkrevealer</FILE>
<TITLE>GtkRevealer</TITLE>
GtkRevealer
GtkRevealerClass
gtk_revealer_new
gtk_revealer_get_reveal_child
gtk_revealer_set_reveal_child
@@ -6833,15 +6898,11 @@ gtk_popover_set_pointing_to
gtk_popover_get_pointing_to
gtk_popover_set_position
gtk_popover_get_position
GtkPopoverConstraint
gtk_popover_set_constrain_to
gtk_popover_get_constrain_to
gtk_popover_set_autohide
gtk_popover_get_autohide
gtk_popover_set_has_arrow
gtk_popover_get_has_arrow
gtk_popover_set_default_widget
gtk_popover_get_default_widget
<SUBSECTION Standard>
GTK_TYPE_POPOVER
GTK_IS_POPOVER
@@ -7028,6 +7089,8 @@ GtkEventControllerMotion
gtk_event_controller_motion_new
gtk_event_controller_motion_get_pointer_origin
gtk_event_controller_motion_get_pointer_target
gtk_event_controller_motion_contains_pointer
gtk_event_controller_motion_is_pointer
<SUBSECTION Standard>
GTK_TYPE_EVENT_CONTROLLER_MOTION
@@ -7596,8 +7659,8 @@ gtk_fixed_layout_new
<SUBSECTION>
GtkFixedLayoutChild
gtk_fixed_layout_child_set_position
gtk_fixed_layout_child_get_position
gtk_fixed_layout_child_set_transform
gtk_fixed_layout_child_get_transform
<SUBSECTION Standard>
GTK_TYPE_FIXED_LAYOUT
@@ -7726,3 +7789,77 @@ gtk_constraint_guide_get_max_size
GTK_TYPE_CONSTRAINT_GUIDE
gtk_constraint_guide_get_tyoe
</SECTION>
<SECTION>
<FILE>gtkexpression</FILE>
GtkExpression
GtkExpressionWatch
GtkExpressionNotify
gtk_expression_ref
gtk_expression_unref
gtk_expression_get_value_type
gtk_expression_is_static
gtk_expression_evaluate
gtk_expression_watch
gtk_expression_bind
gtk_expression_watch_ref
gtk_expression_watch_unref
gtk_expression_watch_evaluate
gtk_expression_watch_unwatch
<SUBSECTION>
gtk_property_expression_new
gtk_constant_expression_new
gtk_constant_expression_new_for_value
gtk_object_expression_new
gtk_closure_expression_new
gtk_cclosure_expression_new
<SUBSECTION Standard>
GTK_IS_EXPRESSION
GTK_TYPE_EXPRESSION
<SUBSECTION Private>
gtk_expression_get_type
</SECTION>
<SECTION>
<FILE>gtkstringfilter</FILE>
GtkStringFilter
GtkStringFilterMatchMode
gtk_string_filter_new
gtk_string_filter_get_search
gtk_string_filter_set_search
gtk_string_filter_get_expression
gtk_string_filter_set_expression
gtk_string_filter_get_ignore_case
gtk_string_filter_set_ignore_case
gtk_string_filter_get_match_mode
gtk_string_filter_set_match_mode
<SUBSECTION Private>
gtk_string_filter_get_type
</SECTION>
<SECTION>
<FILE>gtkdropdown</FILE>
<TITLE>GtkDropDown</TITLE>
GtkDropDown
gtk_drop_down_new
gtk_drop_down_set_from_strings
gtk_drop_down_set_model
gtk_drop_down_get_model
gtk_drop_down_set_selected
gtk_drop_down_get_selected
gtk_drop_down_set_factory
gtk_drop_down_get_factory
gtk_drop_down_set_list_factory
gtk_drop_down_get_list_factory
gtk_drop_down_set_expression
gtk_drop_down_get_expression
gtk_drop_down_set_enable_search
gtk_drop_down_get_enable_search
<SUBSECTION Standard>
GTK_TYPE_DROP_DOWN
<SUBSECTION Private>
gtk_drop_down_get_type
</SECTION>
+24 -1
View File
@@ -9,6 +9,7 @@ gtk_accessible_get_type
gtk_actionable_get_type
gtk_action_bar_get_type
gtk_adjustment_get_type
gtk_any_filter_get_type
gtk_app_chooser_get_type
gtk_app_chooser_button_get_type
gtk_app_chooser_dialog_get_type
@@ -22,8 +23,11 @@ gtk_bin_get_type
gtk_bin_layout_get_type
gtk_box_get_type
gtk_box_layout_get_type
gtk_builder_get_type
gtk_buildable_get_type
gtk_builder_cscope_get_type
gtk_builder_get_type
gtk_builder_list_item_factory_get_type
gtk_builder_scope_get_type
gtk_button_get_type
gtk_calendar_get_type
gtk_cell_area_get_type
@@ -47,6 +51,8 @@ gtk_color_button_get_type
gtk_color_chooser_get_type
gtk_color_chooser_dialog_get_type
gtk_color_chooser_widget_get_type
gtk_column_view_get_type
gtk_column_view_column_get_type
gtk_combo_box_get_type
gtk_combo_box_text_get_type
gtk_constraint_get_type
@@ -54,9 +60,13 @@ gtk_constraint_guide_get_type
gtk_constraint_layout_get_type
gtk_constraint_target_get_type
gtk_container_get_type
gtk_custom_sorter_get_type
gtk_css_provider_get_type
gtk_custom_filter_get_type
gtk_dialog_get_type
gtk_directory_list_get_type
gtk_drawing_area_get_type
gtk_drop_down_get_type
gtk_editable_get_type
gtk_entry_buffer_get_type
gtk_entry_completion_get_type
@@ -66,12 +76,14 @@ gtk_event_controller_key_get_type
gtk_event_controller_legacy_get_type
gtk_event_controller_motion_get_type
gtk_event_controller_scroll_get_type
gtk_every_filter_get_type
gtk_expander_get_type
gtk_file_chooser_button_get_type
gtk_file_chooser_dialog_get_type
gtk_file_chooser_get_type
gtk_file_chooser_widget_get_type
gtk_file_filter_get_type
gtk_filter_get_type
gtk_filter_list_model_get_type
gtk_fixed_get_type
gtk_fixed_layout_get_type
@@ -97,6 +109,7 @@ gtk_gl_area_get_type
gtk_grid_get_type
gtk_grid_layout_child_get_type
gtk_grid_layout_get_type
gtk_grid_view_get_type
gtk_header_bar_get_type
gtk_icon_theme_get_type
gtk_icon_view_get_type
@@ -109,9 +122,12 @@ gtk_label_get_type
gtk_layout_child_get_type
gtk_layout_manager_get_type
gtk_link_button_get_type
gtk_list_item_get_type
gtk_list_item_factory_get_type
gtk_list_store_get_type
gtk_list_box_get_type
gtk_list_box_row_get_type
gtk_list_view_get_type
gtk_lock_button_get_type
gtk_map_list_model_get_type
gtk_media_controls_get_type
@@ -125,6 +141,7 @@ gtk_menu_shell_get_type
gtk_menu_tool_button_get_type
gtk_message_dialog_get_type
gtk_mount_operation_get_type
gtk_multi_filter_get_type
gtk_multi_sorter_get_type
gtk_native_get_type
gtk_no_selection_get_type
@@ -175,11 +192,13 @@ gtk_shortcuts_window_get_type
gtk_shortcuts_section_get_type
gtk_shortcuts_group_get_type
gtk_shortcuts_shortcut_get_type
gtk_signal_list_item_factory_get_type
gtk_single_selection_get_type
gtk_size_group_get_type
gtk_slice_list_model_get_type
gtk_snapshot_get_type
gtk_sort_list_model_get_type
gtk_sorter_get_type
gtk_spin_button_get_type
gtk_spinner_get_type
gtk_stack_get_type
@@ -187,6 +206,8 @@ gtk_stack_page_get_type
gtk_stack_sidebar_get_type
gtk_stack_switcher_get_type
gtk_statusbar_get_type
gtk_string_filter_get_type
gtk_string_sorter_get_type
gtk_switch_get_type
gtk_level_bar_get_type
gtk_style_context_get_type
@@ -206,7 +227,9 @@ gtk_tool_button_get_type
gtk_tool_item_get_type
gtk_tree_drag_dest_get_type
gtk_tree_drag_source_get_type
gtk_tree_expander_get_type
gtk_tree_list_model_get_type
gtk_tree_list_row_get_type
gtk_tree_list_row_sorter_get_type
gtk_tree_model_filter_get_type
gtk_tree_model_get_type
+14
View File
@@ -21,6 +21,13 @@ private_headers = [
'gtkcolorplaneprivate.h',
'gtkcolorscaleprivate.h',
'gtkcolorswatchprivate.h',
'gtkcolumnviewcellprivate.h',
'gtkcolumnviewcolumnprivate.h',
'gtkcolumnviewlayoutprivate.h',
'gtkcolumnlistitemfactoryprivate.h',
'gtkcolumviewprivate.h',
'gtkcolumnviewsorterprivate.h',
'gtkcolumnviewtitleprivate.h',
'gtkcomboboxprivate.h',
'gtkcontainerprivate.h',
'gtkconstraintexpressionprivate.h',
@@ -131,6 +138,11 @@ private_headers = [
'gtkimmoduleprivate.h',
'gtkkineticscrollingprivate.h',
'gtklabelprivate.h',
'gtklistbaseprivate.h',
'gtklistitemprivate.h',
'gtklistitemfactoryprivate.h',
'gtklistitemmanagerprivate.h',
'gtklistitemwidgetprivate.h',
'gtklockbuttonprivate.h',
'gtkmagnifierprivate.h',
'gtkmediafileprivate.h',
@@ -178,8 +190,10 @@ private_headers = [
'gtktextchildprivate.h',
'gtktextdisplayprivate.h',
'gtktexthandleprivate.h',
'gtktexthistoryprivate.h',
'gtktextiterprivate.h',
'gtktextlayoutprivate.h',
'gtktextlinedisplaycacheprivate.h',
'gtktextmarkprivate.h',
'gtktexttagprivate.h',
'gtktextviewprivate.h',
+341
View File
@@ -0,0 +1,341 @@
/*
* Copyright (C) 2018 Matthias Clasen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <gio/gio.h>
#include <gio/gunixfdlist.h>
#include "filetransferportalprivate.h"
static GDBusProxy *file_transfer_proxy = NULL;
static GDBusProxy *
ensure_file_transfer_portal (void)
{
if (file_transfer_proxy == NULL)
{
GError *error = NULL;
file_transfer_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES
| G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS
| G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
NULL,
"org.freedesktop.portal.Documents",
"/org/freedesktop/portal/documents",
"org.freedesktop.portal.FileTransfer",
NULL, &error);
if (error)
{
g_debug ("Failed to get proxy: %s", error->message);
g_error_free (error);
}
}
if (file_transfer_proxy)
{
char *owner = g_dbus_proxy_get_name_owner (file_transfer_proxy);
if (owner)
{
g_free (owner);
return file_transfer_proxy;
}
}
return NULL;
}
gboolean
file_transfer_portal_available (void)
{
gboolean available;
ensure_file_transfer_portal ();
available = file_transfer_proxy != NULL;
g_clear_object (&file_transfer_proxy);
return available;
}
typedef struct {
GTask *task;
const char **files;
int len;
int start;
} AddFileData;
static void add_files (GDBusProxy *proxy,
AddFileData *afd);
static void
add_files_done (GObject *object,
GAsyncResult *result,
gpointer data)
{
GDBusProxy *proxy = G_DBUS_PROXY (object);
AddFileData *afd = data;
GError *error = NULL;
GVariant *ret;
ret = g_dbus_proxy_call_with_unix_fd_list_finish (proxy, NULL, result, &error);
if (ret == NULL)
{
g_task_return_error (afd->task, error);
g_object_unref (afd->task);
g_free (afd);
return;
}
g_variant_unref (ret);
if (afd->start >= afd->len)
{
g_task_return_boolean (afd->task, TRUE);
g_object_unref (afd->task);
g_free (afd);
return;
}
add_files (proxy, afd);
}
/* We call AddFiles in chunks of 16 to avoid running into
* the per-message fd limit of the bus.
*/
static void
add_files (GDBusProxy *proxy,
AddFileData *afd)
{
GUnixFDList *fd_list;
GVariantBuilder fds;
int i;
char *key;
g_variant_builder_init (&fds, G_VARIANT_TYPE ("ah"));
fd_list = g_unix_fd_list_new ();
for (i = 0; afd->files[afd->start + i]; i++)
{
int fd;
int fd_in;
GError *error = NULL;
if (i == 16)
break;
fd = open (afd->files[afd->start + i], O_PATH | O_CLOEXEC);
if (fd == -1)
{
g_task_return_new_error (afd->task, G_IO_ERROR, g_io_error_from_errno (errno),
"Failed to open %s", afd->files[afd->start + i]);
g_object_unref (afd->task);
g_free (afd);
g_object_unref (fd_list);
return;
}
fd_in = g_unix_fd_list_append (fd_list, fd, &error);
close (fd);
if (fd_in == -1)
{
g_task_return_error (afd->task, error);
g_object_unref (afd->task);
g_free (afd);
g_object_unref (fd_list);
return;
}
g_variant_builder_add (&fds, "h", fd_in);
}
afd->start += 16;
key = (char *)g_object_get_data (G_OBJECT (afd->task), "key");
g_dbus_proxy_call_with_unix_fd_list (proxy,
"AddFiles",
g_variant_new ("(sah)", key, &fds),
0, -1,
fd_list,
NULL,
add_files_done, afd);
g_object_unref (fd_list);
}
static void
start_session_done (GObject *object,
GAsyncResult *result,
gpointer data)
{
GDBusProxy *proxy = G_DBUS_PROXY (object);
AddFileData *afd = data;
GError *error = NULL;
GVariant *ret;
const char *key;
ret = g_dbus_proxy_call_finish (proxy, result, &error);
if (ret == NULL)
{
g_task_return_error (afd->task, error);
g_object_unref (afd->task);
g_free (afd);
return;
}
g_variant_get (ret, "(&s)", &key);
g_object_set_data_full (G_OBJECT (afd->task), "key", g_strdup (key), g_free);
g_variant_unref (ret);
add_files (proxy, afd);
}
void
file_transfer_portal_register_files (const char **files,
gboolean writable,
GAsyncReadyCallback callback,
gpointer data)
{
GTask *task;
GDBusProxy *proxy;
AddFileData *afd;
GVariantBuilder options;
task = g_task_new (NULL, NULL, callback, data);
proxy = ensure_file_transfer_portal ();
if (proxy == NULL)
{
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
"No portal found");
g_object_unref (task);
return;
}
afd = g_new (AddFileData, 1);
afd->task = task;
afd->files = files;
afd->len = g_strv_length ((char **)files);
afd->start = 0;
g_variant_builder_init (&options, G_VARIANT_TYPE_VARDICT);
g_variant_builder_add (&options, "{sv}", "writable", g_variant_new_boolean (writable));
g_variant_builder_add (&options, "{sv}", "autostop", g_variant_new_boolean (TRUE));
g_dbus_proxy_call (proxy, "StartTransfer",
g_variant_new ("(a{sv})", &options),
0, -1, NULL, start_session_done, afd);
}
gboolean
file_transfer_portal_register_files_finish (GAsyncResult *result,
char **key,
GError **error)
{
if (g_task_propagate_boolean (G_TASK (result), error))
{
*key = g_strdup (g_object_get_data (G_OBJECT (result), "key"));
return TRUE;
}
return FALSE;
}
static void
retrieve_files_done (GObject *object,
GAsyncResult *result,
gpointer data)
{
GDBusProxy *proxy = G_DBUS_PROXY (object);
GTask *task = data;
GError *error = NULL;
GVariant *ret;
char **files;
ret = g_dbus_proxy_call_finish (proxy, result, &error);
if (ret == NULL)
{
g_task_return_error (task, error);
g_object_unref (task);
return;
}
g_variant_get (ret, "(^a&s)", &files);
g_object_set_data_full (G_OBJECT (task), "files", g_strdupv (files), (GDestroyNotify)g_strfreev);
g_variant_unref (ret);
g_task_return_boolean (task, TRUE);
}
void
file_transfer_portal_retrieve_files (const char *key,
GAsyncReadyCallback callback,
gpointer data)
{
GDBusProxy *proxy;
GTask *task;
GVariantBuilder options;
task = g_task_new (NULL, NULL, callback, data);
proxy = ensure_file_transfer_portal ();
if (proxy == NULL)
{
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
"No portal found");
g_object_unref (task);
return;
}
g_variant_builder_init (&options, G_VARIANT_TYPE_VARDICT);
g_dbus_proxy_call (proxy,
"RetrieveFiles",
g_variant_new ("(sa{sv})", key, &options),
0, -1, NULL,
retrieve_files_done, task);
}
gboolean
file_transfer_portal_retrieve_files_finish (GAsyncResult *result,
char ***files,
GError **error)
{
if (g_task_propagate_boolean (G_TASK (result), error))
{
*files = g_strdupv (g_object_get_data (G_OBJECT (result), "files"));
return TRUE;
}
return FALSE;
}
+39
View File
@@ -0,0 +1,39 @@
/*
* Copyright (C) 2018 Matthias Clasen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __FILE_TRANSFER_PROTOCOL_H__
#define __FILE_TRANSFER_PROTOCOL_H__
gboolean file_transfer_portal_available (void);
void file_transfer_portal_register_files (const char **files,
gboolean writable,
GAsyncReadyCallback callback,
gpointer data);
gboolean file_transfer_portal_register_files_finish (GAsyncResult *result,
char **key,
GError **error);
void file_transfer_portal_retrieve_files (const char *key,
GAsyncReadyCallback callback,
gpointer data);
gboolean file_transfer_portal_retrieve_files_finish (GAsyncResult *result,
char ***files,
GError **error);
#endif
-8
View File
@@ -22,20 +22,12 @@
#ifndef __GI_SCANNER__
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkAppLaunchContext, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkClipboard, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkContentProvider, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkCursor, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkDevice, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkDisplay, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkDisplayManager, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkDrag, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkDrawContext, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkFrameClock, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkGLContext, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkKeymap, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkMonitor, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkSeat, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkVulkanContext, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkSurface, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkContentFormats, gdk_content_formats_unref)
+2 -5
View File
@@ -32,14 +32,11 @@
G_BEGIN_DECLS
#define GDK_TYPE_CAIRO_CONTEXT (gdk_cairo_context_get_type ())
#define GDK_CAIRO_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_CAIRO_CONTEXT, GdkCairoContext))
#define GDK_IS_CAIRO_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_CAIRO_CONTEXT))
#define GDK_CAIRO_ERROR (gdk_cairo_error_quark ())
#define GDK_TYPE_CAIRO_CONTEXT (gdk_cairo_context_get_type ())
GDK_AVAILABLE_IN_ALL
GType gdk_cairo_context_get_type (void) G_GNUC_CONST;
GDK_DECLARE_EXPORTED_TYPE (GdkCairoContext, gdk_cairo_context, GDK, CAIRO_CONTEXT)
GDK_AVAILABLE_IN_ALL
cairo_t * gdk_cairo_context_cairo_create (GdkCairoContext *self);
-6
View File
@@ -29,12 +29,6 @@
G_BEGIN_DECLS
#define GDK_CAIRO_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_CAIRO_CONTEXT, GdkCairoContextClass))
#define GDK_IS_CAIRO_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_CAIRO_CONTEXT))
#define GDK_CAIRO_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_CAIRO_CONTEXT, GdkCairoContextClass))
typedef struct _GdkCairoContextClass GdkCairoContextClass;
struct _GdkCairoContext
{
GdkDrawContext parent_instance;
+1
View File
@@ -1054,6 +1054,7 @@ gdk_clipboard_write_serialize_done (GObject *content,
g_object_unref (task);
}
void
gdk_clipboard_write_async (GdkClipboard *clipboard,
const char *mime_type,
+1 -4
View File
@@ -31,11 +31,8 @@
G_BEGIN_DECLS
#define GDK_TYPE_CLIPBOARD (gdk_clipboard_get_type ())
#define GDK_CLIPBOARD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_CLIPBOARD, GdkClipboard))
#define GDK_IS_CLIPBOARD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_CLIPBOARD))
GDK_AVAILABLE_IN_ALL
GType gdk_clipboard_get_type (void) G_GNUC_CONST;
GDK_DECLARE_EXPORTED_TYPE (GdkClipboard, gdk_clipboard, GDK, CLIPBOARD)
GDK_AVAILABLE_IN_ALL
GdkDisplay * gdk_clipboard_get_display (GdkClipboard *clipboard);
-6
View File
@@ -22,12 +22,6 @@
G_BEGIN_DECLS
#define GDK_CLIPBOARD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_CLIPBOARD, GdkClipboardClass))
#define GDK_IS_CLIPBOARD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_CLIPBOARD))
#define GDK_CLIPBOARD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_CLIPBOARD, GdkClipboardClass))
typedef struct _GdkClipboardClass GdkClipboardClass;
struct _GdkClipboard
{
GObject parent;
+102
View File
@@ -22,6 +22,7 @@
#include "gdkcontentdeserializer.h"
#include "gdkcontentformats.h"
#include "filetransferportalprivate.h"
#include "gdktexture.h"
#include <gdk-pixbuf/gdk-pixbuf.h>
@@ -690,6 +691,93 @@ string_deserializer (GdkContentDeserializer *deserializer)
g_object_unref (filter);
}
static void
portal_finish (GObject *object,
GAsyncResult *result,
gpointer deserializer)
{
char **files = NULL;
GError *error = NULL;
GValue *value;
if (!file_transfer_portal_retrieve_files_finish (result, &files, &error))
{
gdk_content_deserializer_return_error (deserializer, error);
return;
}
value = gdk_content_deserializer_get_value (deserializer);
if (G_VALUE_HOLDS (value, G_TYPE_FILE))
{
if (files[0] != NULL)
g_value_take_object (value, g_file_new_for_path (files[0]));
}
else
{
GSList *l = NULL;
gsize i;
for (i = 0; files[i] != NULL; i++)
l = g_slist_prepend (l, g_file_new_for_path (files[i]));
g_value_take_boxed (value, g_slist_reverse (l));
}
g_strfreev (files);
gdk_content_deserializer_return_success (deserializer);
}
static void
portal_file_deserializer_finish (GObject *source,
GAsyncResult *result,
gpointer deserializer)
{
GOutputStream *stream = G_OUTPUT_STREAM (source);
GError *error = NULL;
gssize written;
char *key;
written = g_output_stream_splice_finish (stream, result, &error);
if (written < 0)
{
gdk_content_deserializer_return_error (deserializer, error);
return;
}
/* write terminating NULL */
if (!g_output_stream_write (stream, "", 1, NULL, &error))
{
gdk_content_deserializer_return_error (deserializer, error);
return;
}
key = g_memory_output_stream_steal_data (G_MEMORY_OUTPUT_STREAM (stream));
if (key == NULL)
{
deserialize_not_found (deserializer);
return;
}
file_transfer_portal_retrieve_files (key, portal_finish, deserializer);
gdk_content_deserializer_set_task_data (deserializer, key, g_free);
}
static void
portal_file_deserializer (GdkContentDeserializer *deserializer)
{
GOutputStream *output;
output = g_memory_output_stream_new_resizable ();
g_output_stream_splice_async (output,
gdk_content_deserializer_get_input_stream (deserializer),
G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
gdk_content_deserializer_get_priority (deserializer),
gdk_content_deserializer_get_cancellable (deserializer),
portal_file_deserializer_finish,
deserializer);
g_object_unref (output);
}
static void
file_uri_deserializer_finish (GObject *source,
GAsyncResult *result,
@@ -764,6 +852,7 @@ init (void)
static gboolean initialized = FALSE;
GSList *formats, *f;
const char *charset;
gboolean has_portal;
if (initialized)
return;
@@ -816,11 +905,24 @@ init (void)
g_slist_free (formats);
has_portal = file_transfer_portal_available ();
if (has_portal)
gdk_content_register_deserializer ("application/vnd.portal.files",
GDK_TYPE_FILE_LIST,
portal_file_deserializer,
NULL,
NULL);
gdk_content_register_deserializer ("text/uri-list",
GDK_TYPE_FILE_LIST,
file_uri_deserializer,
NULL,
NULL);
if (has_portal)
gdk_content_register_deserializer ("application/vnd.portal.files",
G_TYPE_FILE,
portal_file_deserializer,
NULL,
NULL);
gdk_content_register_deserializer ("text/uri-list",
G_TYPE_FILE,
file_uri_deserializer,
+73
View File
@@ -23,6 +23,7 @@
#include "gdkcontentformats.h"
#include "gdkpixbuf.h"
#include "filetransferportalprivate.h"
#include "gdktextureprivate.h"
#include <gdk-pixbuf/gdk-pixbuf.h>
@@ -701,6 +702,63 @@ file_serializer_finish (GObject *source,
gdk_content_serializer_return_success (serializer);
}
static void
portal_ready (GObject *object,
GAsyncResult *result,
gpointer serializer)
{
GError *error = NULL;
char *key;
if (!file_transfer_portal_register_files_finish (result, &key, &error))
{
gdk_content_serializer_return_error (serializer, error);
return;
}
g_output_stream_write_all_async (gdk_content_serializer_get_output_stream (serializer),
key,
strlen (key) + 1,
gdk_content_serializer_get_priority (serializer),
gdk_content_serializer_get_cancellable (serializer),
file_serializer_finish,
serializer);
gdk_content_serializer_set_task_data (serializer, key, g_free);
}
static void
portal_file_serializer (GdkContentSerializer *serializer)
{
GFile *file;
const GValue *value;
GPtrArray *files;
files = g_ptr_array_new_with_free_func (g_free);
value = gdk_content_serializer_get_value (serializer);
if (G_VALUE_HOLDS (value, G_TYPE_FILE))
{
file = g_value_get_object (gdk_content_serializer_get_value (serializer));
if (file)
g_ptr_array_add (files, g_file_get_path (file));
g_ptr_array_add (files, NULL);
}
else if (G_VALUE_HOLDS (value, GDK_TYPE_FILE_LIST))
{
GSList *l;
for (l = g_value_get_boxed (value); l; l = l->next)
g_ptr_array_add (files, g_file_get_path (l->data));
g_ptr_array_add (files, NULL);
}
/* this call doesn't copy the strings, so keep the array around until the registration is done */
file_transfer_portal_register_files ((const char **)files->pdata, TRUE, portal_ready, serializer);
gdk_content_serializer_set_task_data (serializer, files, (GDestroyNotify)g_ptr_array_unref);
}
static void
file_uri_serializer (GdkContentSerializer *serializer)
{
@@ -808,6 +866,7 @@ init (void)
static gboolean initialized = FALSE;
GSList *formats, *f;
const char *charset;
gboolean has_portal;
if (initialized)
return;
@@ -863,6 +922,14 @@ init (void)
g_slist_free (formats);
has_portal = file_transfer_portal_available ();
if (has_portal)
gdk_content_register_serializer (G_TYPE_FILE,
"application/vnd.portal.files",
portal_file_serializer,
NULL,
NULL);
gdk_content_register_serializer (G_TYPE_FILE,
"text/uri-list",
file_uri_serializer,
@@ -873,6 +940,12 @@ init (void)
file_text_serializer,
NULL,
NULL);
if (has_portal)
gdk_content_register_serializer (GDK_TYPE_FILE_LIST,
"application/vnd.portal.files",
portal_file_serializer,
NULL,
NULL);
gdk_content_register_serializer (GDK_TYPE_FILE_LIST,
"text/uri-list",
file_uri_serializer,
+1 -7
View File
@@ -35,14 +35,8 @@
G_BEGIN_DECLS
#define GDK_TYPE_CURSOR (gdk_cursor_get_type ())
#define GDK_CURSOR(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_CURSOR, GdkCursor))
#define GDK_IS_CURSOR(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_CURSOR))
/* Cursors
*/
GDK_AVAILABLE_IN_ALL
GType gdk_cursor_get_type (void) G_GNUC_CONST;
GDK_DECLARE_EXPORTED_TYPE (GdkCursor, gdk_cursor, GDK, CURSOR)
GDK_AVAILABLE_IN_ALL
GdkCursor* gdk_cursor_new_from_texture (GdkTexture *texture,
-6
View File
@@ -29,12 +29,6 @@
G_BEGIN_DECLS
#define GDK_CURSOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_CURSOR, GdkCursorClass))
#define GDK_IS_CURSOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_CURSOR))
#define GDK_CURSOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_CURSOR, GdkCursorClass))
typedef struct _GdkCursorClass GdkCursorClass;
struct _GdkCursor
{
GObject parent_instance;
+2 -5
View File
@@ -29,8 +29,8 @@
G_BEGIN_DECLS
#define GDK_TYPE_DEVICE (gdk_device_get_type ())
#define GDK_DEVICE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDK_TYPE_DEVICE, GdkDevice))
#define GDK_IS_DEVICE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDK_TYPE_DEVICE))
GDK_AVAILABLE_IN_ALL
GDK_DECLARE_EXPORTED_TYPE (GdkDevice, gdk_device, GDK, DEVICE)
typedef struct _GdkTimeCoord GdkTimeCoord;
@@ -121,9 +121,6 @@ struct _GdkTimeCoord
gdouble axes[GDK_MAX_TIMECOORD_AXES];
};
GDK_AVAILABLE_IN_ALL
GType gdk_device_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_ALL
const gchar * gdk_device_get_name (GdkDevice *device);
GDK_AVAILABLE_IN_ALL
-5
View File
@@ -25,11 +25,6 @@
G_BEGIN_DECLS
#define GDK_DEVICE_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), GDK_TYPE_DEVICE, GdkDeviceClass))
#define GDK_IS_DEVICE_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), GDK_TYPE_DEVICE))
#define GDK_DEVICE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDK_TYPE_DEVICE, GdkDeviceClass))
typedef struct _GdkDeviceClass GdkDeviceClass;
typedef struct _GdkDeviceKey GdkDeviceKey;
struct _GdkDeviceKey
+3 -5
View File
@@ -34,12 +34,10 @@
G_BEGIN_DECLS
#define GDK_TYPE_DISPLAY (gdk_display_get_type ())
#define GDK_DISPLAY(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_DISPLAY, GdkDisplay))
#define GDK_IS_DISPLAY(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_DISPLAY))
#define GDK_TYPE_DISPLAY (gdk_display_get_type ())
GDK_AVAILABLE_IN_ALL
GType gdk_display_get_type (void) G_GNUC_CONST;
GDK_DECLARE_EXPORTED_TYPE (GdkDisplay, gdk_display, GDK, DISPLAY)
GDK_AVAILABLE_IN_ALL
GdkDisplay *gdk_display_open (const gchar *display_name);
-7
View File
@@ -30,13 +30,6 @@
G_BEGIN_DECLS
#define GDK_DISPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_DISPLAY, GdkDisplayClass))
#define GDK_IS_DISPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_DISPLAY))
#define GDK_DISPLAY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_DISPLAY, GdkDisplayClass))
typedef struct _GdkDisplayClass GdkDisplayClass;
/* Tracks information about the device grab on this display */
typedef struct
{
+2 -5
View File
@@ -36,8 +36,8 @@
G_BEGIN_DECLS
#define GDK_TYPE_DRAG (gdk_drag_get_type ())
#define GDK_DRAG(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_DRAG, GdkDrag))
#define GDK_IS_DRAG(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_DRAG))
GDK_AVAILABLE_IN_ALL
GDK_DECLARE_EXPORTED_TYPE (GdkDrag, gdk_drag, GDK, DRAG)
/**
* GdkDragCancelReason:
@@ -53,9 +53,6 @@ typedef enum {
GDK_DRAG_CANCEL_ERROR
} GdkDragCancelReason;
GDK_AVAILABLE_IN_ALL
GType gdk_drag_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_ALL
GdkDisplay * gdk_drag_get_display (GdkDrag *drag);
GDK_AVAILABLE_IN_ALL
-7
View File
@@ -23,13 +23,6 @@
G_BEGIN_DECLS
#define GDK_DRAG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_DRAG, GdkDragClass))
#define GDK_IS_DRAG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_DRAG))
#define GDK_DRAG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_DRAG, GdkDragClass))
typedef struct _GdkDragClass GdkDragClass;
struct _GdkDragClass {
GObjectClass parent_class;
+2 -5
View File
@@ -30,12 +30,9 @@
G_BEGIN_DECLS
#define GDK_TYPE_DRAW_CONTEXT (gdk_draw_context_get_type ())
#define GDK_DRAW_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_DRAW_CONTEXT, GdkDrawContext))
#define GDK_IS_DRAW_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_DRAW_CONTEXT))
#define GDK_TYPE_DRAW_CONTEXT (gdk_draw_context_get_type ())
GDK_AVAILABLE_IN_ALL
GType gdk_draw_context_get_type (void) G_GNUC_CONST;
GDK_DECLARE_EXPORTED_TYPE (GdkDrawContext, gdk_draw_context, GDK, DRAW_CONTEXT)
GDK_AVAILABLE_IN_ALL
GdkDisplay * gdk_draw_context_get_display (GdkDrawContext *context);
-6
View File
@@ -25,12 +25,6 @@
G_BEGIN_DECLS
#define GDK_DRAW_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_DRAW_CONTEXT, GdkDrawContextClass))
#define GDK_IS_DRAW_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_DRAW_CONTEXT))
#define GDK_DRAW_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_DRAW_CONTEXT, GdkDrawContextClass))
typedef struct _GdkDrawContextClass GdkDrawContextClass;
struct _GdkDrawContext
{
GObject parent_instance;
+1 -6
View File
@@ -30,14 +30,9 @@
G_BEGIN_DECLS
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkDrop, g_object_unref)
#define GDK_TYPE_DROP (gdk_drop_get_type ())
#define GDK_DROP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_DROP, GdkDrop))
#define GDK_IS_DROP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_DROP))
GDK_AVAILABLE_IN_ALL
GType gdk_drop_get_type (void) G_GNUC_CONST;
GDK_DECLARE_EXPORTED_TYPE (GdkDrop, gdk_drop, GDK, DROP)
GDK_AVAILABLE_IN_ALL
GdkDisplay * gdk_drop_get_display (GdkDrop *self);
-7
View File
@@ -25,13 +25,6 @@
G_BEGIN_DECLS
#define GDK_DROP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_DROP, GdkDropClass))
#define GDK_IS_DROP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_DROP))
#define GDK_DROP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_DROP, GdkDropClass))
typedef struct _GdkDropClass GdkDropClass;
struct _GdkDrop {
GObject parent_instance;
};
+4 -7
View File
@@ -30,18 +30,15 @@
G_BEGIN_DECLS
#define GDK_TYPE_GL_CONTEXT (gdk_gl_context_get_type ())
#define GDK_GL_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_GL_CONTEXT, GdkGLContext))
#define GDK_IS_GL_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_GL_CONTEXT))
#define GDK_GL_ERROR (gdk_gl_error_quark ())
#define GDK_TYPE_GL_CONTEXT (gdk_gl_context_get_type ())
GDK_AVAILABLE_IN_ALL
GDK_DECLARE_EXPORTED_TYPE (GdkGLContext, gdk_gl_context, GDK, GL_CONTEXT)
GDK_AVAILABLE_IN_ALL
GQuark gdk_gl_error_quark (void);
GDK_AVAILABLE_IN_ALL
GType gdk_gl_context_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_ALL
GdkDisplay * gdk_gl_context_get_display (GdkGLContext *context);
GDK_AVAILABLE_IN_ALL
-6
View File
@@ -26,12 +26,6 @@
G_BEGIN_DECLS
#define GDK_GL_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_GL_CONTEXT, GdkGLContextClass))
#define GDK_IS_GL_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_GL_CONTEXT))
#define GDK_GL_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_GL_CONTEXT, GdkGLContextClass))
typedef struct _GdkGLContextClass GdkGLContextClass;
struct _GdkGLContext
{
GdkDrawContext parent_instance;
+1 -10
View File
@@ -29,17 +29,8 @@
G_BEGIN_DECLS
#define GDK_TYPE_GL_TEXTURE (gdk_gl_texture_get_type ())
#define GDK_GL_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_GL_TEXTURE, GdkGLTexture))
#define GDK_IS_GL_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_GL_TEXTURE))
typedef struct _GdkGLTexture GdkGLTexture;
typedef struct _GdkGLTextureClass GdkGLTextureClass;
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkGLTexture, g_object_unref)
GDK_AVAILABLE_IN_ALL
GType gdk_gl_texture_get_type (void) G_GNUC_CONST;
GDK_DECLARE_EXPORTED_TYPE (GdkGLTexture, gdk_gl_texture, GDK, GL_TEXTURE)
GDK_AVAILABLE_IN_ALL
GdkTexture * gdk_gl_texture_new (GdkGLContext *context,
+1 -11
View File
@@ -87,18 +87,8 @@ typedef enum {
#endif
#define GDK_TYPE_MEMORY_TEXTURE (gdk_memory_texture_get_type ())
#define GDK_MEMORY_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_MEMORY_TEXTURE, GdkMemoryTexture))
#define GDK_IS_MEMORY_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_MEMORY_TEXTURE))
typedef struct _GdkMemoryTexture GdkMemoryTexture;
typedef struct _GdkMemoryTextureClass GdkMemoryTextureClass;
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkMemoryTexture, g_object_unref)
GDK_AVAILABLE_IN_ALL
GType gdk_memory_texture_get_type (void) G_GNUC_CONST;
GDK_DECLARE_EXPORTED_TYPE (GdkMemoryTexture, gdk_memory_texture, GDK, MEMORY_TEXTURE)
GDK_AVAILABLE_IN_ALL
GdkTexture * gdk_memory_texture_new (int width,
+4 -4
View File
@@ -2438,10 +2438,10 @@ gdk_surface_get_root_coords (GdkSurface *surface,
* @offset_x: X position of @shape_region in @surface coordinates
* @offset_y: Y position of @shape_region in @surface coordinates
*
* Like gdk_surface_shape_combine_region(), but the shape applies
* only to event handling. Mouse events which happen while
* the pointer position corresponds to an unset bit in the
* mask will be passed on the surface below @surface.
* Apply the region to the surface for the purpose of event
* handling. Mouse events which happen while the pointer position
* corresponds to an unset bit in the mask will be passed on the
* surface below @surface.
*
* An input shape is typically used with RGBA surfaces.
* The alpha channel of the surface defines which pixels are
+1 -10
View File
@@ -30,17 +30,8 @@
G_BEGIN_DECLS
#define GDK_TYPE_TEXTURE (gdk_texture_get_type ())
#define GDK_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_TEXTURE, GdkTexture))
#define GDK_IS_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_TEXTURE))
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkTexture, g_object_unref)
typedef struct _GdkTextureClass GdkTextureClass;
GDK_AVAILABLE_IN_ALL
GType gdk_texture_get_type (void) G_GNUC_CONST;
GDK_DECLARE_EXPORTED_TYPE (GdkTexture, gdk_texture, GDK, TEXTURE)
GDK_AVAILABLE_IN_ALL
GdkTexture * gdk_texture_new_for_pixbuf (GdkPixbuf *pixbuf);
-4
View File
@@ -5,10 +5,6 @@
G_BEGIN_DECLS
#define GDK_TEXTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_TEXTURE, GdkTextureClass))
#define GDK_IS_TEXTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_TEXTURE))
#define GDK_TEXTURE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_TEXTURE, GdkTextureClass))
struct _GdkTexture
{
GObject parent_instance;
+20
View File
@@ -591,6 +591,26 @@ typedef enum
*/
#define GDK_ACTION_ALL (GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK)
#define GDK_DECLARE_EXPORTED_TYPE(ModuleObjName, module_obj_name, MODULE, OBJ_NAME) \
GType module_obj_name##_get_type (void) G_GNUC_CONST; \
G_GNUC_BEGIN_IGNORE_DEPRECATIONS \
typedef struct _##ModuleObjName ModuleObjName; \
typedef struct _##ModuleObjName##Class ModuleObjName##Class; \
\
G_DEFINE_AUTOPTR_CLEANUP_FUNC(ModuleObjName, g_object_unref) \
\
G_GNUC_UNUSED static inline ModuleObjName * MODULE##_##OBJ_NAME (gconstpointer ptr) { \
return G_TYPE_CHECK_INSTANCE_CAST (ptr, module_obj_name##_get_type (), ModuleObjName); } \
G_GNUC_UNUSED static inline ModuleObjName##Class * MODULE##_##OBJ_NAME##_CLASS (gconstpointer ptr) { \
return G_TYPE_CHECK_CLASS_CAST (ptr, module_obj_name##_get_type (), ModuleObjName##Class); } \
G_GNUC_UNUSED static inline gboolean MODULE##_IS_##OBJ_NAME (gpointer ptr) { \
return G_TYPE_CHECK_INSTANCE_TYPE (ptr, module_obj_name##_get_type ()); } \
G_GNUC_UNUSED static inline gboolean MODULE##_IS_##OBJ_NAME##_CLASS (gpointer ptr) { \
return G_TYPE_CHECK_CLASS_TYPE (ptr, module_obj_name##_get_type ()); } \
G_GNUC_UNUSED static inline ModuleObjName##Class * MODULE##_##OBJ_NAME##_GET_CLASS (gpointer ptr) { \
return G_TYPE_INSTANCE_GET_CLASS (ptr, module_obj_name##_get_type (), ModuleObjName##Class); } \
G_GNUC_END_IGNORE_DEPRECATIONS
G_END_DECLS
#endif /* __GDK_TYPES_H__ */
+2 -5
View File
@@ -35,17 +35,14 @@
G_BEGIN_DECLS
#define GDK_TYPE_VULKAN_CONTEXT (gdk_vulkan_context_get_type ())
#define GDK_VULKAN_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_VULKAN_CONTEXT, GdkVulkanContext))
#define GDK_IS_VULKAN_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_VULKAN_CONTEXT))
GDK_AVAILABLE_IN_ALL
GDK_DECLARE_EXPORTED_TYPE (GdkVulkanContext, gdk_vulkan_context, GDK, VULKAN_CONTEXT)
#define GDK_VULKAN_ERROR (gdk_vulkan_error_quark ())
GDK_AVAILABLE_IN_ALL
GQuark gdk_vulkan_error_quark (void);
GDK_AVAILABLE_IN_ALL
GType gdk_vulkan_context_get_type (void) G_GNUC_CONST;
#ifndef __GI_SCANNER__
#ifdef GDK_RENDERING_VULKAN
-6
View File
@@ -32,12 +32,6 @@
G_BEGIN_DECLS
#define GDK_VULKAN_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_VULKAN_CONTEXT, GdkVulkanContextClass))
#define GDK_IS_VULKAN_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_VULKAN_CONTEXT))
#define GDK_VULKAN_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_VULKAN_CONTEXT, GdkVulkanContextClass))
typedef struct _GdkVulkanContextClass GdkVulkanContextClass;
struct _GdkVulkanContext
{
GdkDrawContext parent_instance;
+1
View File
@@ -19,6 +19,7 @@ gdk_public_sources = files([
'gdkdrawcontext.c',
'gdkdrop.c',
'gdkevents.c',
'filetransferportal.c',
'gdkframeclock.c',
'gdkframeclockidle.c',
'gdkframetimings.c',
+15 -5
View File
@@ -40,7 +40,9 @@ gdk_win32_vulkan_context_create_surface (GdkVulkanContext *context,
{
GdkSurface *window = gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (context));
GdkDisplay *display = gdk_draw_context_get_display (GDK_DRAW_CONTEXT (context));
GdkWin32Surface *win32_surface = GDK_WIN32_SURFACE (window);
VkWin32SurfaceCreateInfoKHR info;
VkResult result;
info.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
info.pNext = NULL;
@@ -55,11 +57,19 @@ gdk_win32_vulkan_context_create_surface (GdkVulkanContext *context,
*/
gdk_display_sync (display);
return GDK_VK_CHECK (vkCreateWin32SurfaceKHR,
gdk_vulkan_context_get_instance (context),
&info,
NULL,
surface);
result = GDK_VK_CHECK (vkCreateWin32SurfaceKHR,
gdk_vulkan_context_get_instance (context),
&info,
NULL,
surface);
if (result == VK_SUCCESS)
win32_surface->suppress_layered ++;
if (win32_surface->suppress_layered == 1)
_gdk_win32_surface_update_style_bits (window);
return result;
}
static void
+3
View File
@@ -305,6 +305,9 @@ gdk_x11_display_set_cursor_theme (GdkDisplay *display,
if (size > 0)
XcursorSetDefaultSize (xdisplay, size);
if (GDK_X11_DISPLAY (display)->cursors == NULL)
return;
g_hash_table_iter_init (&iter, GDK_X11_DISPLAY (display)->cursors);
while (g_hash_table_iter_next (&iter, &cursor, &xcursor))
{
+4 -2
View File
@@ -1842,8 +1842,10 @@ gdk_drag_anim_timeout (gpointer data)
gdk_surface_show (drag->drag_surface);
gdk_x11_surface_move (drag->drag_surface,
drag->last_x + (drag->start_x - drag->last_x) * t,
drag->last_y + (drag->start_y - drag->last_y) * t);
(drag->last_x - drag->hot_x) +
(drag->start_x - drag->last_x) * t,
(drag->last_y - drag->hot_y) +
(drag->start_y - drag->last_y) * t);
gdk_surface_set_opacity (drag->drag_surface, 1.0 - f);
return G_SOURCE_CONTINUE;
-11
View File
@@ -67,7 +67,6 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkEditable, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkEntry, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkEntryBuffer, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkEntryCompletion, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkEventController, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkExpander, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkFileChooserButton, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkFileChooserDialog, g_object_unref)
@@ -82,15 +81,6 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkFontChooserDialog, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkFontChooserWidget, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkFrame, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkGLArea, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkGesture, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkGestureDrag, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkGestureLongPress, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkGestureClick, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkGesturePan, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkGestureRotate, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkGestureSingle, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkGestureSwipe, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkGestureZoom, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkGrid, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkGridView, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkHeaderBar, g_object_unref)
@@ -179,7 +169,6 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkViewport, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkVolumeButton, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkPaperSize, gtk_paper_size_free)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkRecentInfo, gtk_recent_info_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkSelectionData, gtk_selection_data_free)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkTextIter, gtk_text_iter_free)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkTreeIter, gtk_tree_iter_free)
+2 -2
View File
@@ -124,7 +124,7 @@
#include <gtk/gtkfilefilter.h>
#include <gtk/gtkfilter.h>
#include <gtk/gtkfilterlistmodel.h>
#include <gtk/gtkfilters.h>
#include <gtk/gtkcustomfilter.h>
#include <gtk/gtkflattenlistmodel.h>
#include <gtk/gtkflowbox.h>
#include <gtk/gtkfontbutton.h>
@@ -180,6 +180,7 @@
#include <gtk/gtkmenutoolbutton.h>
#include <gtk/gtkmessagedialog.h>
#include <gtk/gtkmountoperation.h>
#include <gtk/gtkmultifilter.h>
#include <gtk/gtkmultiselection.h>
#include <gtk/gtkmultisorter.h>
#include <gtk/gtknative.h>
@@ -220,7 +221,6 @@
#include <gtk/gtksearchentry.h>
#include <gtk/gtkselection.h>
#include <gtk/gtkselectionmodel.h>
#include <gtk/gtkselectionmonitor.h>
#include <gtk/gtkseparator.h>
#include <gtk/gtkseparatormenuitem.h>
#include <gtk/gtkseparatortoolitem.h>
+21 -21
View File
@@ -1100,7 +1100,7 @@ gtk_builder_create_bindings (GtkBuilder *builder,
}
else
{
gtk_expression_bind (expression, info->target, object, info->target_pspec->name);
gtk_expression_bind (expression, info->target, info->target_pspec->name, object);
}
}
@@ -1710,29 +1710,29 @@ gtk_builder_expose_object (GtkBuilder *builder,
/**
* gtk_builder_get_current_object:
* @self: a #GtkBuilder
* @builder: a #GtkBuilder
*
* Gets the current object set via gtk_builder_set_current_object().
*
* Returns: (nullable) (transfer none): the current object
**/
GObject *
gtk_builder_get_current_object (GtkBuilder *self)
gtk_builder_get_current_object (GtkBuilder *builder)
{
GtkBuilderPrivate *priv = gtk_builder_get_instance_private (self);
GtkBuilderPrivate *priv = gtk_builder_get_instance_private (builder);
g_return_val_if_fail (GTK_IS_BUILDER (self), NULL);
g_return_val_if_fail (GTK_IS_BUILDER (builder), NULL);
return priv->current_object;
}
/**
* gtk_builder_set_current_object:
* @self: a #GtkBuilder
* @builder: a #GtkBuilder
* @current_object: (nullable) (transfer none): the new current object or
* %NULL for none
*
* Sets the current object for the @self. The current object can be
* Sets the current object for the @builder. The current object can be
* tought of as the `this` object that the builder is working for and
* will often be used as the default object when an object is optional.
*
@@ -1742,23 +1742,23 @@ gtk_builder_get_current_object (GtkBuilder *self)
* will be %NULL.
**/
void
gtk_builder_set_current_object (GtkBuilder *self,
gtk_builder_set_current_object (GtkBuilder *builder,
GObject *current_object)
{
GtkBuilderPrivate *priv = gtk_builder_get_instance_private (self);
GtkBuilderPrivate *priv = gtk_builder_get_instance_private (builder);
g_return_if_fail (GTK_IS_BUILDER (self));
g_return_if_fail (GTK_IS_BUILDER (builder));
g_return_if_fail (current_object || G_IS_OBJECT (current_object));
if (!g_set_object (&priv->current_object, current_object))
return;
g_object_notify_by_pspec (G_OBJECT (self), builder_props[PROP_CURRENT_OBJECT]);
g_object_notify_by_pspec (G_OBJECT (builder), builder_props[PROP_CURRENT_OBJECT]);
}
/**
* gtk_builder_get_scope:
* @self: a #GtkBuilder
* @builder: a #GtkBuilder
*
* Gets the scope in use that was set via gtk_builder_set_scope().
*
@@ -1767,18 +1767,18 @@ gtk_builder_set_current_object (GtkBuilder *self,
* Returns: (transfer none): the current scope
**/
GtkBuilderScope *
gtk_builder_get_scope (GtkBuilder *self)
gtk_builder_get_scope (GtkBuilder *builder)
{
GtkBuilderPrivate *priv = gtk_builder_get_instance_private (self);
GtkBuilderPrivate *priv = gtk_builder_get_instance_private (builder);
g_return_val_if_fail (GTK_IS_BUILDER (self), NULL);
g_return_val_if_fail (GTK_IS_BUILDER (builder), NULL);
return priv->scope;
}
/**
* gtk_builder_set_current_object:
* @self: a #GtkBuilder
* gtk_builder_set_scope:
* @builder: a #GtkBuilder
* @scope: (nullable) (transfer none): the scope to use or
* %NULL for the default
*
@@ -1789,12 +1789,12 @@ gtk_builder_get_scope (GtkBuilder *self)
* See the #GtkBuilderScope documentation for details.
**/
void
gtk_builder_set_scope (GtkBuilder *self,
gtk_builder_set_scope (GtkBuilder *builder,
GtkBuilderScope *scope)
{
GtkBuilderPrivate *priv = gtk_builder_get_instance_private (self);
GtkBuilderPrivate *priv = gtk_builder_get_instance_private (builder);
g_return_if_fail (GTK_IS_BUILDER (self));
g_return_if_fail (GTK_IS_BUILDER (builder));
g_return_if_fail (scope == NULL || GTK_IS_BUILDER_SCOPE (scope));
if (scope && priv->scope == scope)
@@ -1807,7 +1807,7 @@ gtk_builder_set_scope (GtkBuilder *self,
else
priv->scope = gtk_builder_cscope_new ();
g_object_notify_by_pspec (G_OBJECT (self), builder_props[PROP_SCOPE]);
g_object_notify_by_pspec (G_OBJECT (builder), builder_props[PROP_SCOPE]);
}
static gboolean
+2 -2
View File
@@ -137,9 +137,9 @@ void gtk_builder_expose_object (GtkBuilder *builder,
const gchar *name,
GObject *object);
GDK_AVAILABLE_IN_ALL
GObject * gtk_builder_get_current_object (GtkBuilder *self);
GObject * gtk_builder_get_current_object (GtkBuilder *builder);
GDK_AVAILABLE_IN_ALL
void gtk_builder_set_current_object (GtkBuilder *self,
void gtk_builder_set_current_object (GtkBuilder *builder,
GObject *current_object);
GDK_AVAILABLE_IN_ALL
void gtk_builder_set_translation_domain (GtkBuilder *builder,
+75 -2
View File
@@ -22,16 +22,47 @@
#include "gtkbuilderlistitemfactory.h"
#include "gtkbuilder.h"
#include "gtkbuilderprivate.h"
#include "gtkintl.h"
#include "gtklistitemfactoryprivate.h"
#include "gtklistitemprivate.h"
/**
* SECTION:gtkbuilderlistitemfactory
* @Tiitle: GtkBuilderListItemFactory
* @Short_description: A listitem factory using ui files
*
* #GtkBuilderListItemFactory is a #GtkListItemFactory that creates
* widgets by instantiating #GtkBuilder UI templates. The templates
* must be extending #GtkListItem, and typically use #GtkExpressions
* to obtain data from the items in the model.
*
* Example:
* |[
* <interface>
* <template class="GtkListItem">
* <property name="child">
* <object class="GtkLabel">
* <property name="xalign">0</property>
* <binding name="label">
* <lookup name="name" type="SettingsKey">
* <lookup name="item">GtkListItem</lookup>
* </lookup>
* </binding>
* </object>
* </property>
* </template>
* </interface>
* ]|
*/
struct _GtkBuilderListItemFactory
{
GtkListItemFactory parent_instance;
GtkBuilderScope *scope;
GBytes *bytes;
GBytes *data;
char *resource;
};
@@ -71,8 +102,8 @@ gtk_builder_list_item_factory_setup (GtkListItemFactory *factory,
gtk_builder_set_scope (builder, self->scope);
if (!gtk_builder_extend_with_template (builder, G_OBJECT (list_item), GTK_TYPE_LIST_ITEM,
(const gchar *)g_bytes_get_data (self->bytes, NULL),
g_bytes_get_size (self->bytes),
(const gchar *)g_bytes_get_data (self->data, NULL),
g_bytes_get_size (self->data),
&error))
{
g_critical ("Error building template for list item: %s", error->message);
@@ -130,6 +161,27 @@ gtk_builder_list_item_factory_set_bytes (GtkBuilderListItemFactory *self,
}
self->bytes = g_bytes_ref (bytes);
if (!_gtk_buildable_parser_is_precompiled (g_bytes_get_data (bytes, NULL), g_bytes_get_size (bytes)))
{
GError *error = NULL;
GBytes *data;
data = _gtk_buildable_parser_precompile (g_bytes_get_data (bytes, NULL),
g_bytes_get_size (bytes),
&error);
if (data == NULL)
{
g_warning ("Failed to precompile template for GtkBuilderListItemFactory: %s", error->message);
g_error_free (error);
self->data = g_bytes_ref (bytes);
}
else
{
self->data = data;
}
}
return TRUE;
}
@@ -189,6 +241,7 @@ gtk_builder_list_item_factory_finalize (GObject *object)
g_clear_object (&self->scope);
g_bytes_unref (self->bytes);
g_bytes_unref (self->data);
g_free (self->resource);
G_OBJECT_CLASS (gtk_builder_list_item_factory_parent_class)->finalize (object);
@@ -250,6 +303,16 @@ gtk_builder_list_item_factory_init (GtkBuilderListItemFactory *self)
{
}
/**
* gtk_builder_list_item_factory_new_from_bytes:
* @scope: (nullable) (transfer none): A scope to use when instantiating
* @bytes: the bytes containing the ui file to instantiate
*
* Creates s new #GtkBuilderListItemFactory that instantiates widgets
* using @bytes as the data to pass to #GtkBuilder.
*
* Returns: a new #GtkBuilderListItemFactory
**/
GtkListItemFactory *
gtk_builder_list_item_factory_new_from_bytes (GtkBuilderScope *scope,
GBytes *bytes)
@@ -262,6 +325,16 @@ gtk_builder_list_item_factory_new_from_bytes (GtkBuilderScope *scope,
NULL);
}
/**
* gtk_builder_list_item_factory_new_from_resource:
* @scope: (nullable) (transfer none): A scope to use when instantiating
* @resource_path: valid path to a resource that contains the data
*
* Creates s new #GtkBuilderListItemFactory that instantiates widgets
* using data read from the given @resource_path to pass to #GtkBuilder.
*
* Returns: a new #GtkBuilderListItemFactory
**/
GtkListItemFactory *
gtk_builder_list_item_factory_new_from_resource (GtkBuilderScope *scope,
const char *resource_path)
+39 -6
View File
@@ -1042,7 +1042,7 @@ free_expression_info (ExpressionInfo *info)
switch (info->expression_type)
{
case EXPRESSION_EXPRESSION:
gtk_expression_unref (info->expression);
g_clear_pointer (&info->expression, gtk_expression_unref);
break;
case EXPRESSION_CONSTANT:
@@ -1371,6 +1371,7 @@ expression_info_construct (GtkBuilder *builder,
{
GtkExpression *expression;
GType type;
GParamSpec *pspec;
if (info->property.expression)
{
@@ -1378,6 +1379,7 @@ expression_info_construct (GtkBuilder *builder,
if (expression == NULL)
return NULL;
free_expression_info (info->property.expression);
info->property.expression = NULL;
}
else
expression = NULL;
@@ -1391,13 +1393,44 @@ expression_info_construct (GtkBuilder *builder,
g_set_error (error,
GTK_BUILDER_ERROR,
GTK_BUILDER_ERROR_MISSING_ATTRIBUTE,
"%s:%d:%d Lookups require a type attribute if they don't have an expression.",
"???", 0, 0);
"Lookups require a type attribute if they don't have an expression.");
return NULL;
}
expression = gtk_property_expression_new (type,
expression,
info->property.property_name);
if (g_type_is_a (type, G_TYPE_OBJECT))
{
GObjectClass *class = g_type_class_ref (type);
pspec = g_object_class_find_property (class, info->property.property_name);
g_type_class_unref (class);
}
else if (g_type_is_a (type, G_TYPE_INTERFACE))
{
GTypeInterface *iface = g_type_default_interface_ref (type);
pspec = g_object_interface_find_property (iface, info->property.property_name);
g_type_default_interface_unref (iface);
}
else
{
g_set_error (error,
GTK_BUILDER_ERROR,
GTK_BUILDER_ERROR_MISSING_ATTRIBUTE,
"Type `%s` does not support properties",
g_type_name (type));
return NULL;
}
if (pspec == NULL)
{
g_set_error (error,
GTK_BUILDER_ERROR,
GTK_BUILDER_ERROR_MISSING_ATTRIBUTE,
"Type `%s` does not have a property name `%s`",
g_type_name (type), info->property.property_name);
return NULL;
}
expression = gtk_property_expression_new_for_pspec (expression, pspec);
g_free (info->property.property_name);
info->expression_type = EXPRESSION_EXPRESSION;
info->expression = expression;
+20 -10
View File
@@ -44,7 +44,7 @@
* language which can be created via gtk_builder_cscope_new().
*
* #GtkBuilderCScope instances use symbols explicitly added to @builder
* with prior calls to gtk_builder_scope_add_callback_symbol(). If developers want
* with prior calls to gtk_builder_cscope_add_callback_symbol(). If developers want
* to do that, they are encouraged to create their own scopes for that purpose.
*
* In the case that symbols are not explicitly added; GTK will uses #GModules
@@ -52,7 +52,7 @@
* symbol table. From here it tries to match the signal function names given in the
* interface description with symbols in the application.
*
* Note that unless gtk_builder_scope_add_callback_symbol() is called for
* Note that unless gtk_builder_cscope_add_callback_symbol() is called for
* all signal callbacks which are referenced by the loaded XML, this
* functionality will require that #GModule be supported on the platform.
*/
@@ -187,12 +187,14 @@ gtk_builder_cscope_get_module (GtkBuilderCScope *self)
* GtkWindow -> gtk_window_get_type
* GtkHBox -> gtk_hbox_get_type
* GtkUIManager -> gtk_ui_manager_get_type
* GWeatherLocation -> gweather_location_get_type
* GWeatherLocation -> gweather_location_get_type (split_first_cap == FALSE)
* GThemedIcon -> g_themed_icon_get_type (slit_first_cap == TRUE)
*
* Keep in sync with testsuite/gtk/typename.c !
*/
static gchar *
type_name_mangle (const gchar *name)
type_name_mangle (const gchar *name,
gboolean split_first_cap)
{
GString *symbol_name = g_string_new ("");
gint i;
@@ -201,8 +203,9 @@ type_name_mangle (const gchar *name)
{
/* skip if uppercase, first or previous is uppercase */
if ((name[i] == g_ascii_toupper (name[i]) &&
i > 0 && name[i-1] != g_ascii_toupper (name[i-1])) ||
(i > 2 && name[i] == g_ascii_toupper (name[i]) &&
((i > 0 && name[i-1] != g_ascii_toupper (name[i-1])) ||
(i == 1 && name[0] == g_ascii_toupper (name[0]) && split_first_cap))) ||
(i > 2 && name[i] == g_ascii_toupper (name[i]) &&
name[i-1] == g_ascii_toupper (name[i-1]) &&
name[i-2] == g_ascii_toupper (name[i-2])))
g_string_append_c (symbol_name, '_');
@@ -219,14 +222,21 @@ gtk_builder_cscope_resolve_type_lazily (GtkBuilderCScope *self,
{
GModule *module;
GType (*func) (void);
gchar *symbol;
char *symbol;
GType gtype = G_TYPE_INVALID;
module = gtk_builder_cscope_get_module (self);
if (!module)
return G_TYPE_INVALID;
symbol = type_name_mangle (name);
symbol = type_name_mangle (name, TRUE);
if (g_module_symbol (module, symbol, (gpointer)&func))
gtype = func ();
g_free (symbol);
symbol = type_name_mangle (name, FALSE);
if (g_module_symbol (module, symbol, (gpointer)&func))
gtype = func ();
@@ -449,7 +459,7 @@ gtk_builder_cscope_add_callback_symbol (GtkBuilderCScope *self,
* @...: A list of callback name and callback symbol pairs terminated with %NULL
*
* A convenience function to add many callbacks instead of calling
* gtk_builder_add_callback_symbol() for each symbol.
* gtk_builder_cscope_add_callback_symbol() for each symbol.
*/
void
gtk_builder_cscope_add_callback_symbols (GtkBuilderCScope *self,
@@ -490,7 +500,7 @@ gtk_builder_cscope_add_callback_symbols (GtkBuilderCScope *self,
* @callback_name: The name of the callback
*
* Fetches a symbol previously added to @self
* with gtk_builder_add_callback_symbols().
* with gtk_builder_cscope_add_callback_symbol().
*
* Returns: (nullable): The callback symbol in @builder for @callback_name, or %NULL
*/
+23 -1
View File
@@ -36,7 +36,7 @@ G_DECLARE_INTERFACE (GtkBuilderScope, gtk_builder_scope, GTK, BUILDER_SCOPE, GOb
/**
* GtkBuilderClosureFlags:
* @GTK_BUILDER_CLOSURE_SWAPPED: The closure should be created swapped. See
* g_cclosure_new_swapped() for details.
* g_cclosure_new_swap() for details.
*
* The list of flags that can be passed to gtk_builder_scope_create_closure().
* New values may be added in the future for new features, so external
@@ -48,6 +48,28 @@ typedef enum {
GTK_BUILDER_CLOSURE_SWAPPED = (1 << 0)
} GtkBuilderClosureFlags;
/**
* GtkBuilderScopeInterface:
* @get_type_from_name: Try to lookup a #GType via the its name. See
* gtk_builder_get_type_from_name() for more details.
* The C implementation will use g_type_from_name() and if that fails try to guess the
* correct function name for registering the type and then use dlsym() to load it.
* The default implementation just tries g_type_from_name() and otherwise fails.
* @get_type_from_function: Try to lookup a #GType via the given function name, specified
* explicitly in a GtkBuilder file, like via the "type-func" attribute in the "<object>" tag.
* This function is very rarely used.
* The C implementation will use dlsym() and call the resulting function as a #GTypeFunc.
* The default implementation will fail and just return %G_TYPE_INVALID.
* @create_closure: Create a closure with the given arguments. See gtk_builder_create_closure()
* for more details on those.
* The C implementation will try to use dlsym() to locate the function name and then
* g_cclosure_new() to create a closure for the symbol.
* The default implementation just fails and returns %NULL.
*
* The virtual function table to implement for #GtkBuilderScope implementations.
* Default implementations for each function do exist, but they usually just fail,
* so it is suggested that implementations implement all of them.
*/
struct _GtkBuilderScopeInterface
{
/*< private >*/
+731 -67
View File
@@ -34,6 +34,13 @@
#include "gtkprivate.h"
#include "gtkscrollable.h"
#include "gtkwidgetprivate.h"
#include "gtksizerequest.h"
#include "gtkadjustment.h"
#include "gtkgesturedrag.h"
#include "gtkeventcontrollermotion.h"
#include "gtkeventcontrollerkey.h"
#include "gtklistbaseprivate.h"
#include "gtkdnd.h"
/**
* SECTION:gtkcolumnview
@@ -43,6 +50,12 @@
*
* GtkColumnView is a widget to present a view into a large dynamic list of items
* using multiple columns.
*
* It supports sorting that can be customized by the user by clicking on column
* view headers. To set this up, the #GtkSorter returned by gtk_column_view_get_sorter()
* must be attached to a sort model for the data that the view is showing, and the
* columns must have sorters attached to them by calling gtk_column_view_column_set_sorter().
* The initial sort order can be set with gtk_column_view_sort_by_column().
*/
struct _GtkColumnView
@@ -57,6 +70,21 @@ struct _GtkColumnView
GtkColumnListItemFactory *factory;
GtkSorter *sorter;
GtkAdjustment *hadjustment;
gboolean in_column_resize;
gboolean in_column_reorder;
int drag_pos;
int drag_x;
int drag_offset;
int drag_column_x;
GtkGesture *drag_gesture;
guint autoscroll_id;
double autoscroll_x;
double autoscroll_delta;
};
struct _GtkColumnViewClass
@@ -72,10 +100,12 @@ enum
PROP_HSCROLL_POLICY,
PROP_MODEL,
PROP_SHOW_SEPARATORS,
PROP_SORTER,
PROP_VADJUSTMENT,
PROP_VSCROLL_POLICY,
PROP_SORT_MODEL,
PROP_SORTER,
PROP_SINGLE_CLICK_ACTIVATE,
PROP_ENABLE_RUBBERBAND,
PROP_SEARCH_FILTER,
N_PROPS
};
@@ -163,48 +193,77 @@ gtk_column_view_allocate_columns (GtkColumnView *self,
int width)
{
GtkScrollablePolicy scroll_policy;
int col_min, col_nat, widget_min, widget_nat, extra, col_size, x;
int col_min, col_nat, extra, col_size, x;
int n, n_expand, expand_size, n_extra;
guint i;
GtkRequestedSize *sizes;
gtk_column_view_measure_across (self, &col_min, &col_nat);
gtk_widget_measure (GTK_WIDGET (self),
GTK_ORIENTATION_HORIZONTAL, -1,
&widget_min, &widget_nat,
NULL, NULL);
scroll_policy = gtk_scrollable_get_hscroll_policy (GTK_SCROLLABLE (self->listview));
if (scroll_policy == GTK_SCROLL_MINIMUM)
{
extra = widget_min - col_min;
col_size = col_min;
}
else
{
extra = widget_nat - col_nat;
col_size = col_nat;
}
width -= extra;
width = MAX (width, col_size);
x = 0;
for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (self->columns)); i++)
n = g_list_model_get_n_items (G_LIST_MODEL (self->columns));
n_expand = 0;
sizes = g_newa (GtkRequestedSize, n);
for (i = 0; i < n; i++)
{
GtkColumnViewColumn *column;
column = g_list_model_get_item (G_LIST_MODEL (self->columns), i);
gtk_column_view_column_measure (column, &col_min, &col_nat);
if (scroll_policy == GTK_SCROLL_MINIMUM)
col_size = col_min;
if (gtk_column_view_column_get_visible (column))
{
gtk_column_view_column_measure (column, &sizes[i].minimum_size, &sizes[i].natural_size);
if (gtk_column_view_column_get_expand (column))
n_expand++;
}
else
col_size = col_nat;
sizes[i].minimum_size = sizes[i].natural_size = 0;
g_object_unref (column);
}
gtk_column_view_column_allocate (column, x, col_size);
x += col_size;
gtk_column_view_measure_across (self, &col_min, &col_nat);
scroll_policy = gtk_scrollable_get_hscroll_policy (GTK_SCROLLABLE (self->listview));
if (scroll_policy == GTK_SCROLL_MINIMUM)
extra = MAX (width - col_min, 0);
else
extra = MAX (width - col_min, col_nat - col_min);
extra = gtk_distribute_natural_allocation (extra, n, sizes);
if (n_expand > 0)
{
expand_size = extra / n_expand;
n_extra = extra % n_expand;
}
else
expand_size = n_extra = 0;
x = 0;
for (i = 0; i < n; i++)
{
GtkColumnViewColumn *column;
column = g_list_model_get_item (G_LIST_MODEL (self->columns), i);
if (gtk_column_view_column_get_visible (column))
{
col_size = sizes[i].minimum_size;
if (gtk_column_view_column_get_expand (column))
{
col_size += expand_size;
if (n_extra > 0)
{
col_size++;
n_extra--;
}
}
gtk_column_view_column_allocate (column, x, col_size);
if (self->in_column_reorder && i == self->drag_pos)
gtk_column_view_column_set_header_position (column, self->drag_x);
x += col_size;
}
g_object_unref (column);
}
return width + extra;
return x;
}
static void
@@ -214,8 +273,9 @@ gtk_column_view_allocate (GtkWidget *widget,
int baseline)
{
GtkColumnView *self = GTK_COLUMN_VIEW (widget);
int full_width, header_height, min, nat;
int full_width, header_height, min, nat, x;
x = gtk_adjustment_get_value (self->hadjustment);
full_width = gtk_column_view_allocate_columns (self, width);
gtk_widget_measure (self->header, GTK_ORIENTATION_VERTICAL, full_width, &min, &nat, NULL, NULL);
@@ -223,11 +283,14 @@ gtk_column_view_allocate (GtkWidget *widget,
header_height = min;
else
header_height = nat;
gtk_widget_allocate (self->header, full_width, header_height, -1, NULL);
gtk_widget_allocate (self->header, full_width, header_height, -1,
gsk_transform_translate (NULL, &GRAPHENE_POINT_INIT (-x, 0)));
gtk_widget_allocate (GTK_WIDGET (self->listview),
full_width, height - header_height, -1,
gsk_transform_translate (NULL, &GRAPHENE_POINT_INIT (0, header_height)));
gsk_transform_translate (NULL, &GRAPHENE_POINT_INIT (-x, header_height)));
gtk_adjustment_configure (self->hadjustment, x, 0, full_width, width * 0.1, width * 0.9, width);
}
static void
@@ -238,6 +301,23 @@ gtk_column_view_activate_cb (GtkListView *listview,
g_signal_emit (self, signals[ACTIVATE], 0, pos);
}
static void
adjustment_value_changed_cb (GtkAdjustment *adjustment,
GtkColumnView *self)
{
gtk_widget_queue_allocate (GTK_WIDGET (self));
}
static void
clear_adjustment (GtkColumnView *self)
{
if (self->hadjustment == NULL)
return;
g_signal_handlers_disconnect_by_func (self->hadjustment, adjustment_value_changed_cb, self);
g_clear_object (&self->hadjustment);
}
static void
gtk_column_view_dispose (GObject *object)
{
@@ -256,6 +336,7 @@ gtk_column_view_dispose (GObject *object)
g_clear_object (&self->factory);
g_clear_object (&self->sorter);
clear_adjustment (self);
G_OBJECT_CLASS (gtk_column_view_parent_class)->dispose (object);
}
@@ -285,7 +366,7 @@ gtk_column_view_get_property (GObject *object,
break;
case PROP_HADJUSTMENT:
g_value_set_object (value, gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (self->listview)));
g_value_set_object (value, self->hadjustment);
break;
case PROP_HSCROLL_POLICY:
@@ -312,6 +393,18 @@ gtk_column_view_get_property (GObject *object,
g_value_set_object (value, self->sorter);
break;
case PROP_SINGLE_CLICK_ACTIVATE:
g_value_set_boolean (value, gtk_column_view_get_single_click_activate (self));
break;
case PROP_ENABLE_RUBBERBAND:
g_value_set_boolean (value, gtk_column_view_get_enable_rubberband (self));
break;
case PROP_SEARCH_FILTER:
g_value_set_object (value, gtk_column_view_get_search_filter (self));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@@ -325,13 +418,24 @@ gtk_column_view_set_property (GObject *object,
GParamSpec *pspec)
{
GtkColumnView *self = GTK_COLUMN_VIEW (object);
GtkAdjustment *adjustment;
switch (property_id)
{
case PROP_HADJUSTMENT:
if (gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (self->listview)) != g_value_get_object (value))
adjustment = g_value_get_object (value);
if (adjustment == NULL)
adjustment = gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
g_object_ref_sink (adjustment);
if (self->hadjustment != adjustment)
{
gtk_scrollable_set_hadjustment (GTK_SCROLLABLE (self->listview), g_value_get_object (value));
clear_adjustment (self);
self->hadjustment = adjustment;
g_signal_connect (adjustment, "value-changed", G_CALLBACK (adjustment_value_changed_cb), self);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_HADJUSTMENT]);
}
break;
@@ -368,6 +472,18 @@ gtk_column_view_set_property (GObject *object,
}
break;
case PROP_SINGLE_CLICK_ACTIVATE:
gtk_column_view_set_single_click_activate (self, g_value_get_boolean (value));
break;
case PROP_ENABLE_RUBBERBAND:
gtk_column_view_set_enable_rubberband (self, g_value_get_boolean (value));
break;
case PROP_SEARCH_FILTER:
gtk_column_view_set_search_filter (self, g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@@ -440,20 +556,54 @@ gtk_column_view_class_init (GtkColumnViewClass *klass)
FALSE,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
properties[PROP_SORT_MODEL] =
g_param_spec_object ("sort-model",
P_("Sort Model"),
P_("Sort Model for the items displayed"),
GTK_TYPE_SORT_LIST_MODEL,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
/**
* GtkColumnView:sorter:
*
* Sorter with the sorting choices of the user
*/
properties[PROP_SORTER] =
g_param_spec_object ("sorter",
P_("Sorter"),
P_("Sorter"),
P_("Sorter with sorting choices of the user"),
GTK_TYPE_SORTER,
G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
/**
* GtkColumnView:single-click-activate:
*
* Activate rows on single click and select them on hover
*/
properties[PROP_SINGLE_CLICK_ACTIVATE] =
g_param_spec_boolean ("single-click-activate",
P_("Single click activate"),
P_("Activate rows on single click"),
FALSE,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
/**
* GtkColumnView:enable-rubberband:
*
* Allow rubberband selection
*/
properties[PROP_ENABLE_RUBBERBAND] =
g_param_spec_boolean ("enable-rubberband",
P_("Enable rubberband selection"),
P_("Allow selecting items by dragging with the mouse"),
FALSE,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
/**
* GtkColumnView:search-filter:
*
* Filter used for search
*/
properties[PROP_SEARCH_FILTER] =
g_param_spec_object ("search-filter",
P_("Search filter"),
P_("Filter used for searching"),
GTK_TYPE_FILTER,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (gobject_class, N_PROPS, properties);
/**
@@ -483,9 +633,366 @@ gtk_column_view_class_init (GtkColumnViewClass *klass)
gtk_widget_class_set_css_name (widget_class, I_("treeview"));
}
static void update_column_resize (GtkColumnView *self,
double x);
static void update_column_reorder (GtkColumnView *self,
double x);
static gboolean
autoscroll_cb (GtkWidget *widget,
GdkFrameClock *frame_clock,
gpointer data)
{
GtkColumnView *self = data;
gtk_adjustment_set_value (self->hadjustment,
gtk_adjustment_get_value (self->hadjustment) + self->autoscroll_delta);
self->autoscroll_x += self->autoscroll_delta;
if (self->in_column_resize)
update_column_resize (self, self->autoscroll_x);
else if (self->in_column_reorder)
update_column_reorder (self, self->autoscroll_x);
return G_SOURCE_CONTINUE;
}
static void
add_autoscroll (GtkColumnView *self,
double x,
double delta)
{
self->autoscroll_x = x;
self->autoscroll_delta = delta;
if (self->autoscroll_id == 0)
self->autoscroll_id = gtk_widget_add_tick_callback (GTK_WIDGET (self), autoscroll_cb, self, NULL);
}
static void
remove_autoscroll (GtkColumnView *self)
{
if (self->autoscroll_id != 0)
{
gtk_widget_remove_tick_callback (GTK_WIDGET (self), self->autoscroll_id);
self->autoscroll_id = 0;
}
}
#define DRAG_WIDTH 6
static gboolean
gtk_column_view_in_resize_rect (GtkColumnView *self,
GtkColumnViewColumn *column,
double x,
double y)
{
GtkWidget *header;
graphene_rect_t rect;
header = gtk_column_view_column_get_header (column);
if (!gtk_widget_compute_bounds (header, self->header, &rect))
return FALSE;
rect.origin.x += rect.size.width - DRAG_WIDTH / 2;
rect.size.width = DRAG_WIDTH;
return graphene_rect_contains_point (&rect, &(graphene_point_t) { x, y});
}
static gboolean
gtk_column_view_in_header (GtkColumnView *self,
GtkColumnViewColumn *column,
double x,
double y)
{
GtkWidget *header;
graphene_rect_t rect;
header = gtk_column_view_column_get_header (column);
if (!gtk_widget_compute_bounds (header, self->header, &rect))
return FALSE;
return graphene_rect_contains_point (&rect, &(graphene_point_t) { x, y});
}
static void
header_drag_begin (GtkGestureDrag *gesture,
double start_x,
double start_y,
GtkColumnView *self)
{
int i, n;
self->drag_pos = -1;
n = g_list_model_get_n_items (G_LIST_MODEL (self->columns));
for (i = 0; !self->in_column_resize && i < n; i++)
{
GtkColumnViewColumn *column = g_list_model_get_item (G_LIST_MODEL (self->columns), i);
if (!gtk_column_view_column_get_visible (column))
{
g_object_unref (column);
continue;
}
if (i + 1 < n &&
gtk_column_view_column_get_resizable (column) &&
gtk_column_view_in_resize_rect (self, column, start_x, start_y))
{
int size;
gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED);
if (!gtk_widget_has_focus (GTK_WIDGET (self)))
gtk_widget_grab_focus (GTK_WIDGET (self));
gtk_column_view_column_get_allocation (column, NULL, &size);
gtk_column_view_column_set_fixed_width (column, size);
self->drag_pos = i;
self->drag_x = start_x - size;
self->in_column_resize = TRUE;
g_object_unref (column);
break;
}
if (gtk_column_view_column_get_reorderable (column) &&
gtk_column_view_in_header (self, column, start_x, start_y))
{
int pos;
gtk_column_view_column_get_allocation (column, &pos, NULL);
self->drag_pos = i;
self->drag_offset = start_x - pos;
g_object_unref (column);
break;
}
g_object_unref (column);
}
}
static void
header_drag_end (GtkGestureDrag *gesture,
double offset_x,
double offset_y,
GtkColumnView *self)
{
double start_x, x;
gtk_gesture_drag_get_start_point (gesture, &start_x, NULL);
x = start_x + offset_x;
remove_autoscroll (self);
if (self->in_column_resize)
{
self->in_column_resize = FALSE;
}
else if (self->in_column_reorder)
{
GdkEventSequence *sequence;
GtkColumnViewColumn *column;
GtkWidget *header;
int i;
self->in_column_reorder = FALSE;
if (self->drag_pos == -1)
return;
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");
sequence = gtk_gesture_single_get_current_sequence (GTK_GESTURE_SINGLE (gesture));
if (!gtk_gesture_handles_sequence (GTK_GESTURE (gesture), sequence))
return;
for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (self->columns)); i++)
{
GtkColumnViewColumn *col = g_list_model_get_item (G_LIST_MODEL (self->columns), i);
if (gtk_column_view_column_get_visible (col))
{
int pos, size;
gtk_column_view_column_get_allocation (col, &pos, &size);
if (pos <= x && x <= pos + size)
{
gtk_column_view_insert_column (self, i, column);
g_object_unref (col);
break;
}
}
g_object_unref (col);
}
g_object_unref (column);
}
}
static void
update_column_resize (GtkColumnView *self,
double x)
{
GtkColumnViewColumn *column;
column = g_list_model_get_item (G_LIST_MODEL (self->columns), self->drag_pos);
gtk_column_view_column_set_fixed_width (column, MAX (x - self->drag_x, 0));
g_object_unref (column);
}
static void
update_column_reorder (GtkColumnView *self,
double x)
{
GtkColumnViewColumn *column;
int width;
int size;
column = g_list_model_get_item (G_LIST_MODEL (self->columns), self->drag_pos);
width = gtk_widget_get_allocated_width (GTK_WIDGET (self->header));
gtk_column_view_column_get_allocation (column, NULL, &size);
self->drag_x = CLAMP (x - self->drag_offset, 0, width - size);
gtk_widget_queue_allocate (GTK_WIDGET (self));
gtk_column_view_column_queue_resize (column);
g_object_unref (column);
}
#define SCROLL_EDGE_SIZE 15
static void
header_drag_update (GtkGestureDrag *gesture,
double offset_x,
double offset_y,
GtkColumnView *self)
{
GdkEventSequence *sequence;
double start_x, x;
sequence = gtk_gesture_single_get_current_sequence (GTK_GESTURE_SINGLE (gesture));
if (!gtk_gesture_handles_sequence (GTK_GESTURE (gesture), sequence))
return;
if (self->drag_pos == -1)
return;
if (!self->in_column_resize && !self->in_column_reorder)
{
if (gtk_drag_check_threshold (GTK_WIDGET (self), 0, 0, offset_x, 0))
{
GtkColumnViewColumn *column;
GtkWidget *header;
column = g_list_model_get_item (G_LIST_MODEL (self->columns), self->drag_pos);
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_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED);
if (!gtk_widget_has_focus (GTK_WIDGET (self)))
gtk_widget_grab_focus (GTK_WIDGET (self));
self->in_column_reorder = TRUE;
g_object_unref (column);
}
}
gtk_gesture_drag_get_start_point (gesture, &start_x, NULL);
x = start_x + offset_x;
if (self->in_column_resize)
update_column_resize (self, x);
else if (self->in_column_reorder)
update_column_reorder (self, x);
if (self->in_column_resize || self->in_column_reorder)
{
double value, page_size, upper;
value = gtk_adjustment_get_value (self->hadjustment);
page_size = gtk_adjustment_get_page_size (self->hadjustment);
upper = gtk_adjustment_get_upper (self->hadjustment);
if (x - value < SCROLL_EDGE_SIZE && value > 0)
add_autoscroll (self, x, - (SCROLL_EDGE_SIZE - (x - value))/3.0);
else if (value + page_size - x < SCROLL_EDGE_SIZE && value + page_size < upper)
add_autoscroll (self, x, (SCROLL_EDGE_SIZE - (value + page_size - x))/3.0);
else
remove_autoscroll (self);
}
}
static void
header_motion (GtkEventControllerMotion *controller,
double x,
double y,
GtkColumnView *self)
{
gboolean cursor_set = FALSE;
int i, n;
n = g_list_model_get_n_items (G_LIST_MODEL (self->columns));
for (i = 0; i < n; i++)
{
GtkColumnViewColumn *column = g_list_model_get_item (G_LIST_MODEL (self->columns), i);
if (!gtk_column_view_column_get_visible (column))
{
g_object_unref (column);
continue;
}
if (i + 1 < n &&
gtk_column_view_column_get_resizable (column) &&
gtk_column_view_in_resize_rect (self, column, x, y))
{
gtk_widget_set_cursor_from_name (self->header, "col-resize");
cursor_set = TRUE;
}
g_object_unref (column);
}
if (!cursor_set)
gtk_widget_set_cursor (self->header, NULL);
}
static gboolean
header_key_pressed (GtkEventControllerKey *controller,
guint keyval,
guint keycode,
GdkModifierType modifiers,
GtkColumnView *self)
{
if (self->in_column_reorder)
{
if (keyval == GDK_KEY_Escape)
gtk_gesture_set_state (self->drag_gesture, GTK_EVENT_SEQUENCE_DENIED);
return TRUE;
}
return FALSE;
}
static void
gtk_column_view_init (GtkColumnView *self)
{
GtkEventController *controller;
self->columns = g_list_store_new (GTK_TYPE_COLUMN_VIEW_COLUMN);
self->header = gtk_list_item_widget_new (NULL, "header");
@@ -493,6 +1000,22 @@ gtk_column_view_init (GtkColumnView *self)
gtk_widget_set_layout_manager (self->header, gtk_column_view_layout_new (self));
gtk_widget_set_parent (self->header, GTK_WIDGET (self));
controller = GTK_EVENT_CONTROLLER (gtk_gesture_drag_new ());
g_signal_connect (controller, "drag-begin", G_CALLBACK (header_drag_begin), self);
g_signal_connect (controller, "drag-update", G_CALLBACK (header_drag_update), self);
g_signal_connect (controller, "drag-end", G_CALLBACK (header_drag_end), self);
gtk_event_controller_set_propagation_phase (controller, GTK_PHASE_CAPTURE);
gtk_widget_add_controller (self->header, controller);
self->drag_gesture = GTK_GESTURE (controller);
controller = gtk_event_controller_motion_new ();
g_signal_connect (controller, "motion", G_CALLBACK (header_motion), self);
gtk_widget_add_controller (self->header, controller);
controller = gtk_event_controller_key_new ();
g_signal_connect (controller, "key-pressed", G_CALLBACK (header_key_pressed), self);
gtk_widget_add_controller (GTK_WIDGET (self), controller);
self->sorter = gtk_column_view_sorter_new ();
self->factory = gtk_column_list_item_factory_new (self);
self->listview = GTK_LIST_VIEW (gtk_list_view_new_with_factory (
@@ -667,6 +1190,7 @@ gtk_column_view_remove_column (GtkColumnView *self,
g_object_unref (item);
if (item == column)
break;
}
gtk_column_view_sorter_remove_column (GTK_COLUMN_VIEW_SORTER (self->sorter), column);
@@ -674,6 +1198,45 @@ gtk_column_view_remove_column (GtkColumnView *self,
g_list_store_remove (self->columns, i);
}
void
gtk_column_view_insert_column (GtkColumnView *self,
guint position,
GtkColumnViewColumn *column)
{
g_return_if_fail (GTK_IS_COLUMN_VIEW (self));
g_return_if_fail (GTK_IS_COLUMN_VIEW_COLUMN (column));
g_return_if_fail (gtk_column_view_column_get_column_view (column) == NULL ||
gtk_column_view_column_get_column_view (column) == self);
g_return_if_fail (position <= g_list_model_get_n_items (G_LIST_MODEL (self->columns)));
g_object_ref (column);
if (gtk_column_view_column_get_column_view (column) == self)
{
guint i;
for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (self->columns)); i++)
{
GtkColumnViewColumn *item = g_list_model_get_item (G_LIST_MODEL (self->columns), i);
g_object_unref (item);
if (item == column)
{
g_list_store_remove (self->columns, i);
break;
}
}
}
else
gtk_column_view_column_set_column_view (column, self);
g_list_store_insert (self->columns, position, column);
gtk_column_view_column_queue_resize (column);
g_object_unref (column);
}
void
gtk_column_view_measure_across (GtkColumnView *self,
int *minimum,
@@ -708,18 +1271,25 @@ gtk_column_view_get_header_widget (GtkColumnView *self)
return GTK_LIST_ITEM_WIDGET (self->header);
}
GtkListView *
gtk_column_view_get_list_view (GtkColumnView *self)
{
return GTK_LIST_VIEW (self->listview);
}
/**
* gtk_column_view_get_sorter:
* @self: a #GtkColumnView
*
* Returns the sorter associated with the column view.
* Returns the sorter associated with users sorting choices in
* the column view.
*
* To enable customizable sorting by clicking on column
* To allow users to customizable sorting by clicking on column
* headers, this sorter needs to be set on the sort
* model(s) underneath the model that is displayed
* by the view.
*
* See gtk_column_view_get_sorter() for setting up
* See gtk_column_view_column_get_sorter() for setting up
* per-column sorting.
*
* Returns: (transfer none): the #GtkSorter of @self
@@ -732,19 +1302,6 @@ gtk_column_view_get_sorter (GtkColumnView *self)
return self->sorter;
}
void
gtk_column_view_active_sorter_changed (GtkColumnView *self)
{
guint i;
for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (self->columns)); i++)
{
GtkColumnViewColumn *column = g_list_model_get_item (G_LIST_MODEL (self->columns), i);
gtk_column_view_column_active_sorter_changed (column);
g_object_unref (column);
}
}
/**
* gtk_column_view_sort_by_column:
* @self: a #GtkColumnView
@@ -756,10 +1313,9 @@ gtk_column_view_active_sorter_changed (GtkColumnView *self)
* This function should be used to set up the initial sorting. At runtime,
* users can change the sorting of a column view by clicking on the list headers.
*
* This call only has an effect if gtk_column_view_set_sort_model() has
* been called to inform the view about the underlying sort model, and
* if gtk_column_view_set_sorter() has been called on @column to associate
* a sorter with the column.
* This call only has an effect if the sorter returned by gtk_column_view_get_sorter()
* is set on a sort model, and gtk_column_view_column_set_sorter() has been called
* on @column to associate a sorter with the column.
*
* If @column is %NULL, the view will be unsorted.
*/
@@ -773,9 +1329,117 @@ gtk_column_view_sort_by_column (GtkColumnView *self,
g_return_if_fail (column == NULL || gtk_column_view_column_get_column_view (column) == self);
if (column == NULL)
gtk_column_view_sorter_reset (GTK_COLUMN_VIEW_SORTER (self->sorter));
gtk_column_view_sorter_clear (GTK_COLUMN_VIEW_SORTER (self->sorter));
else
gtk_column_view_sorter_set_column (GTK_COLUMN_VIEW_SORTER (self->sorter),
column,
direction == GTK_SORT_DESCENDING);
}
/**
* gtk_column_view_set_single_click_activate:
* @self: a #GtkColumnView
* @single_click_activate: %TRUE to activate items on single click
*
* Sets whether rows should be activated on single click and
* selected on hover.
*/
void
gtk_column_view_set_single_click_activate (GtkColumnView *self,
gboolean single_click_activate)
{
g_return_if_fail (GTK_IS_COLUMN_VIEW (self));
if (single_click_activate == gtk_list_view_get_single_click_activate (self->listview))
return;
gtk_list_view_set_single_click_activate (self->listview, single_click_activate);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SINGLE_CLICK_ACTIVATE]);
}
/**
* gtk_column_view_get_single_click_activate:
* @self: a #GtkColumnView
*
* Returns whether rows will be activated on single click and
* selected on hover.
*
* Returns: %TRUE if rows are activated on single click
*/
gboolean
gtk_column_view_get_single_click_activate (GtkColumnView *self)
{
g_return_val_if_fail (GTK_IS_COLUMN_VIEW (self), FALSE);
return gtk_list_view_get_single_click_activate (self->listview);
}
/**
* gtk_column_view_set_enable_rubberband:
* @self: a #GtkColumnView
* @enable_rubberband: %TRUE to enable rubberband selection
*
* Sets whether selections can be changed by dragging with the mouse.
*/
void
gtk_column_view_set_enable_rubberband (GtkColumnView *self,
gboolean enable_rubberband)
{
g_return_if_fail (GTK_IS_COLUMN_VIEW (self));
if (enable_rubberband == gtk_list_view_get_enable_rubberband (self->listview))
return;
gtk_list_view_set_enable_rubberband (self->listview, enable_rubberband);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ENABLE_RUBBERBAND]);
}
/**
* gtk_column_view_get_enable_rubberband:
* @self: a #GtkColumnView
*
* Returns whether rows can be selected by dragging with the mouse.
*
* Returns: %TRUE if rubberband selection is enabled
*/
gboolean
gtk_column_view_get_enable_rubberband (GtkColumnView *self)
{
g_return_val_if_fail (GTK_IS_COLUMN_VIEW (self), FALSE);
return gtk_list_view_get_enable_rubberband (self->listview);
}
void
gtk_column_view_set_search_filter (GtkColumnView *self,
GtkFilter *filter)
{
g_return_if_fail (GTK_IS_COLUMN_VIEW (self));
g_return_if_fail (filter == NULL || GTK_IS_FILTER (filter));
if (filter == gtk_list_view_get_search_filter (GTK_LIST_VIEW (self->listview)))
return;
gtk_list_view_set_search_filter (GTK_LIST_VIEW (self->listview), filter);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SEARCH_FILTER]);
}
GtkFilter *
gtk_column_view_get_search_filter (GtkColumnView *self)
{
g_return_val_if_fail (GTK_IS_COLUMN_VIEW (self), NULL);
return gtk_list_view_get_search_filter (GTK_LIST_VIEW (self->listview));
}
void
gtk_column_view_select_next_match (GtkColumnView *self,
gboolean forward)
{
g_return_if_fail (GTK_IS_COLUMN_VIEW (self));
gtk_list_view_select_next_match (GTK_LIST_VIEW (self->listview), forward);
}
+27
View File
@@ -27,6 +27,7 @@
#include <gtk/gtktypes.h>
#include <gtk/gtksortlistmodel.h>
#include <gtk/gtksorter.h>
#include <gtk/gtkfilter.h>
G_BEGIN_DECLS
@@ -61,6 +62,10 @@ void gtk_column_view_append_column (GtkColumnView
GDK_AVAILABLE_IN_ALL
void gtk_column_view_remove_column (GtkColumnView *self,
GtkColumnViewColumn *column);
GDK_AVAILABLE_IN_ALL
void gtk_column_view_insert_column (GtkColumnView *self,
guint position,
GtkColumnViewColumn *column);
GDK_AVAILABLE_IN_ALL
GListModel * gtk_column_view_get_model (GtkColumnView *self);
@@ -82,6 +87,28 @@ void gtk_column_view_sort_by_column (GtkColumnView
GtkColumnViewColumn *column,
GtkSortType direction);
GDK_AVAILABLE_IN_ALL
void gtk_column_view_set_single_click_activate (GtkColumnView *self,
gboolean single_click_activate);
GDK_AVAILABLE_IN_ALL
gboolean gtk_column_view_get_single_click_activate (GtkColumnView *self);
GDK_AVAILABLE_IN_ALL
void gtk_column_view_set_enable_rubberband (GtkColumnView *self,
gboolean enable_rubberband);
GDK_AVAILABLE_IN_ALL
gboolean gtk_column_view_get_enable_rubberband (GtkColumnView *self);
GDK_AVAILABLE_IN_ALL
void gtk_column_view_set_search_filter (GtkColumnView *self,
GtkFilter *filter);
GDK_AVAILABLE_IN_ALL
GtkFilter * gtk_column_view_get_search_filter (GtkColumnView *self);
GDK_AVAILABLE_IN_ALL
void gtk_column_view_select_next_match (GtkColumnView *self,
gboolean forward);
G_END_DECLS
#endif /* __GTK_COLUMN_VIEW_H__ */
+9
View File
@@ -53,10 +53,18 @@ gtk_column_view_cell_measure (GtkWidget *widget,
int *minimum_baseline,
int *natural_baseline)
{
GtkColumnViewCell *cell = GTK_COLUMN_VIEW_CELL (widget);
GtkWidget *child = gtk_widget_get_first_child (widget);
if (child)
gtk_widget_measure (child, orientation, for_size, minimum, natural, minimum_baseline, natural_baseline);
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
int fixed_width = gtk_column_view_column_get_fixed_width (cell->column);
if (fixed_width > -1)
*minimum = *natural = fixed_width;
}
}
static void
@@ -156,6 +164,7 @@ gtk_column_view_cell_new (GtkColumnViewColumn *column)
cell = g_object_new (GTK_TYPE_COLUMN_VIEW_CELL,
"factory", gtk_column_view_column_get_factory (column),
"visible", gtk_column_view_column_get_visible (column),
NULL);
cell->column = g_object_ref (column);
+476 -10
View File
@@ -60,6 +60,16 @@ struct _GtkColumnViewColumn
int natural_size_request;
int allocation_offset;
int allocation_size;
int header_position;
int fixed_width;
guint visible : 1;
guint resizable : 1;
guint expand : 1;
guint reorderable : 1;
GMenuModel *menu;
/* This list isn't sorted - this is just caching for performance */
GtkColumnViewCell *first_cell; /* no reference, just caching */
@@ -77,6 +87,12 @@ enum
PROP_FACTORY,
PROP_TITLE,
PROP_SORTER,
PROP_VISIBLE,
PROP_RESIZABLE,
PROP_EXPAND,
PROP_REORDERABLE,
PROP_FIXED_WIDTH,
PROP_HEADER_MENU,
N_PROPS
};
@@ -96,6 +112,7 @@ gtk_column_view_column_dispose (GObject *object)
g_clear_object (&self->factory);
g_clear_object (&self->sorter);
g_clear_pointer (&self->title, g_free);
g_clear_object (&self->menu);
G_OBJECT_CLASS (gtk_column_view_column_parent_class)->dispose (object);
}
@@ -126,6 +143,30 @@ gtk_column_view_column_get_property (GObject *object,
g_value_set_object (value, self->sorter);
break;
case PROP_VISIBLE:
g_value_set_boolean (value, self->visible);
break;
case PROP_RESIZABLE:
g_value_set_boolean (value, self->resizable);
break;
case PROP_EXPAND:
g_value_set_boolean (value, self->expand);
break;
case PROP_REORDERABLE:
g_value_set_boolean (value, self->reorderable);
break;
case PROP_FIXED_WIDTH:
g_value_set_int (value, self->fixed_width);
break;
case PROP_HEADER_MENU:
g_value_set_object (value, self->menu);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@@ -154,6 +195,30 @@ gtk_column_view_column_set_property (GObject *object,
gtk_column_view_column_set_sorter (self, g_value_get_object (value));
break;
case PROP_VISIBLE:
gtk_column_view_column_set_visible (self, g_value_get_boolean (value));
break;
case PROP_RESIZABLE:
gtk_column_view_column_set_resizable (self, g_value_get_boolean (value));
break;
case PROP_EXPAND:
gtk_column_view_column_set_expand (self, g_value_get_boolean (value));
break;
case PROP_REORDERABLE:
gtk_column_view_column_set_reorderable (self, g_value_get_boolean (value));
break;
case PROP_FIXED_WIDTH:
gtk_column_view_column_set_fixed_width (self, g_value_get_int (value));
break;
case PROP_HEADER_MENU:
gtk_column_view_column_set_header_menu (self, g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@@ -178,7 +243,7 @@ gtk_column_view_column_class_init (GtkColumnViewColumnClass *klass)
g_param_spec_object ("column-view",
P_("Column view"),
P_("Column view this column is a part of"),
G_TYPE_LIST_MODEL,
GTK_TYPE_COLUMN_VIEW,
G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
/**
@@ -212,6 +277,79 @@ gtk_column_view_column_class_init (GtkColumnViewColumnClass *klass)
GTK_TYPE_SORTER,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
/**
* GtkColumnViewColumn:visible:
*
* Whether this column is visible
*/
properties[PROP_VISIBLE] =
g_param_spec_boolean ("visible",
P_("Visible"),
P_("Whether this column is visible"),
TRUE,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
/**
* GtkColumnViewColumn:resizable:
*
* Whether this column is resizable
*/
properties[PROP_RESIZABLE] =
g_param_spec_boolean ("resizable",
P_("Resizable"),
P_("Whether this column is resizable"),
FALSE,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
/**
* GtkColumnViewColumn:expand:
*
* Column gets share of extra width allocated to the view
*/
properties[PROP_EXPAND] =
g_param_spec_boolean ("expand",
P_("Expand"),
P_("column gets share of extra width"),
FALSE,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
/**
* GtkColumnViewColumn:reorderable:
*
* Whether this column is reorderable
*/
properties[PROP_REORDERABLE] =
g_param_spec_boolean ("reorderable",
P_("Reorderable"),
P_("Whether this column is reorderable"),
FALSE,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
/**
* GtkColumnViewColumn:fixed-width:
*
* If not -1, this is the width that the column is allocated,
* regardless of the size of its content.
*/
properties[PROP_FIXED_WIDTH] =
g_param_spec_int ("fixed-width",
P_("Fixed width"),
P_("Fixed width of this column"),
-1, G_MAXINT, -1,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
/**
* GtkColumnViewColumn:header-menu:
*
* Menu model used to create the context menu for the column header.
*/
properties[PROP_HEADER_MENU] =
g_param_spec_object ("header-menu",
P_("Header menu"),
P_("Menu to use on the title of this column"),
G_TYPE_MENU_MODEL,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (gobject_class, N_PROPS, properties);
}
@@ -220,6 +358,11 @@ gtk_column_view_column_init (GtkColumnViewColumn *self)
{
self->minimum_size_request = -1;
self->natural_size_request = -1;
self->visible = TRUE;
self->resizable = FALSE;
self->expand = FALSE;
self->reorderable = FALSE;
self->fixed_width = -1;
}
/**
@@ -328,6 +471,12 @@ gtk_column_view_column_measure (GtkColumnViewColumn *self,
int *minimum,
int *natural)
{
if (self->fixed_width > -1)
{
self->minimum_size_request = self->fixed_width;
self->natural_size_request = self->fixed_width;
}
if (self->minimum_size_request < 0)
{
GtkColumnViewCell *cell;
@@ -370,6 +519,7 @@ gtk_column_view_column_allocate (GtkColumnViewColumn *self,
{
self->allocation_offset = offset;
self->allocation_size = size;
self->header_position = offset;
}
void
@@ -387,11 +537,14 @@ static void
gtk_column_view_column_create_cells (GtkColumnViewColumn *self)
{
GtkWidget *row;
GtkWidget *list;
if (self->first_cell)
return;
for (row = gtk_widget_get_first_child (GTK_WIDGET (self->view));
list = GTK_WIDGET (gtk_column_view_get_list_view (self->view));
for (row = gtk_widget_get_first_child (list);
row != NULL;
row = gtk_widget_get_next_sibling (row))
{
@@ -478,6 +631,9 @@ void
gtk_column_view_column_set_column_view (GtkColumnViewColumn *self,
GtkColumnView *view)
{
g_return_if_fail (GTK_IS_COLUMN_VIEW_COLUMN (self));
g_return_if_fail (view == NULL || GTK_IS_COLUMN_VIEW (view));
if (self->view == view)
return;
@@ -572,6 +728,26 @@ gtk_column_view_column_get_title (GtkColumnViewColumn *self)
return self->title;
}
#if 0
static void
gtk_column_view_column_add_to_sorter (GtkColumnViewColumn *self)
{
if (self->view == NULL)
return;
gtk_column_view_sorter_add_column (GTK_COLUMN_VIEW_SORTER (gtk_column_view_get_sorter (self->view)), self);
}
#endif
static void
gtk_column_view_column_remove_from_sorter (GtkColumnViewColumn *self)
{
if (self->view == NULL)
return;
gtk_column_view_sorter_remove_column (GTK_COLUMN_VIEW_SORTER (gtk_column_view_get_sorter (self->view)), self);
}
/**
* gtk_column_view_column_set_sorter:
* @self: a #GtkColumnViewColumn
@@ -586,22 +762,17 @@ void
gtk_column_view_column_set_sorter (GtkColumnViewColumn *self,
GtkSorter *sorter)
{
GtkColumnViewSorter *view_sorter;
g_return_if_fail (GTK_IS_COLUMN_VIEW_COLUMN (self));
g_return_if_fail (sorter == NULL || GTK_IS_SORTER (sorter));
if (!g_set_object (&self->sorter, sorter))
return;
gtk_column_view_column_remove_from_sorter (self);
if (self->header)
gtk_column_view_title_update (GTK_COLUMN_VIEW_TITLE (self->header));
view_sorter = GTK_COLUMN_VIEW_SORTER (gtk_column_view_get_sorter (self->view));
if (gtk_column_view_sorter_remove_column (view_sorter, self))
gtk_column_view_active_sorter_changed (self->view);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SORTER]);
}
@@ -622,8 +793,303 @@ gtk_column_view_column_get_sorter (GtkColumnViewColumn *self)
}
void
gtk_column_view_column_active_sorter_changed (GtkColumnViewColumn *self)
gtk_column_view_column_notify_sort (GtkColumnViewColumn *self)
{
if (self->header)
gtk_column_view_title_update (GTK_COLUMN_VIEW_TITLE (self->header));
}
/**
* gtk_column_view_column_set_visible:
* @self: a #GtkColumnViewColumn
* @visible: whether this column should be visible
*
* Sets whether this column should be visible in views.
*/
void
gtk_column_view_column_set_visible (GtkColumnViewColumn *self,
gboolean visible)
{
GtkColumnViewCell *cell;
g_return_if_fail (GTK_IS_COLUMN_VIEW_COLUMN (self));
if (self->visible == visible)
return;
self->visible = visible;
self->minimum_size_request = -1;
self->natural_size_request = -1;
if (self->header)
gtk_widget_set_visible (GTK_WIDGET (self->header), visible);
for (cell = self->first_cell; cell; cell = gtk_column_view_cell_get_next (cell))
{
gtk_widget_set_visible (GTK_WIDGET (cell), visible);
}
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_VISIBLE]);
}
/**
* gtk_column_view_get_visible:
* @self: a #GtkColumnViewColumn
*
* Returns whether this column is visible.
*
* Returns: %TRUE if this column is visible
*/
gboolean
gtk_column_view_column_get_visible (GtkColumnViewColumn *self)
{
g_return_val_if_fail (GTK_IS_COLUMN_VIEW_COLUMN (self), TRUE);
return self->visible;
}
/**
* gtk_column_view_column_set_resizable:
* @self: a #GtkColumnViewColumn
* @resizable: whether this column should be resizable
*
* Sets whether this column should be resizable by dragging.
*/
void
gtk_column_view_column_set_resizable (GtkColumnViewColumn *self,
gboolean resizable)
{
g_return_if_fail (GTK_IS_COLUMN_VIEW_COLUMN (self));
if (self->resizable == resizable)
return;
self->resizable = resizable;
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_RESIZABLE]);
}
/**
* gtk_column_view_get_resizable:
* @self: a #GtkColumnView
*
* Returns whether this column is resizable.
*
* Returns: %TRUE if this column is resizable
*/
gboolean
gtk_column_view_column_get_resizable (GtkColumnViewColumn *self)
{
g_return_val_if_fail (GTK_IS_COLUMN_VIEW_COLUMN (self), TRUE);
return self->resizable;
}
/**
* gtk_column_view_column_set_expand:
* @self: a #GtkColumnViewColumn
* @expand: %TRUE if this column should expand to fill available sace
*
* Sets the column to take available extra space.
*
* The extra space is shared equally amongst all columns that
* have the expand set to %TRUE.
*/
void
gtk_column_view_column_set_expand (GtkColumnViewColumn *self,
gboolean expand)
{
g_return_if_fail (GTK_IS_COLUMN_VIEW_COLUMN (self));
if (self->expand == expand)
return;
self->expand = expand;
if (self->visible && self->view)
gtk_widget_queue_resize (GTK_WIDGET (self->view));
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_EXPAND]);
}
/**
* gtk_column_view_get_expand:
* @self: a #GtkColumnViewColumn
*
* Returns whether this column should expand.
*
* Returns: %TRUE if this column expands
*/
gboolean
gtk_column_view_column_get_expand (GtkColumnViewColumn *self)
{
g_return_val_if_fail (GTK_IS_COLUMN_VIEW_COLUMN (self), TRUE);
return self->expand;
}
/**
* gtk_column_view_column_set_reorderable:
* @self: a #GtkColumnViewColumn
* @reorderable: whether this column should be reorderable
*
* Sets whether this column should be reorderable by dragging.
*/
void
gtk_column_view_column_set_reorderable (GtkColumnViewColumn *self,
gboolean reorderable)
{
g_return_if_fail (GTK_IS_COLUMN_VIEW_COLUMN (self));
if (self->reorderable == reorderable)
return;
self->reorderable = reorderable;
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_REORDERABLE]);
}
/**
* gtk_column_view_get_reorderable:
* @self: a #GtkColumnView
*
* Returns whether this column is reorderable.
*
* Returns: %TRUE if this column is reorderable
*/
gboolean
gtk_column_view_column_get_reorderable (GtkColumnViewColumn *self)
{
g_return_val_if_fail (GTK_IS_COLUMN_VIEW_COLUMN (self), TRUE);
return self->reorderable;
}
/**
* gtk_column_view_column_set_fixed_width:
* @self: a #GtkColumnViewColumn
* @fixed_width: the new fixed width, or -1
*
* If @fixed_width is not -1, sets the fixed width of @column; otherwise
* unsets it.
*
* Setting a fixed width overrides the automatically calculated width.
* Interactive resizing also sets the fixed-width property.
*/
void
gtk_column_view_column_set_fixed_width (GtkColumnViewColumn *self,
int fixed_width)
{
GtkOverflow overflow;
g_return_if_fail (GTK_IS_COLUMN_VIEW_COLUMN (self));
g_return_if_fail (fixed_width >= -1);
if (self->fixed_width == fixed_width)
return;
self->fixed_width = fixed_width;
if (fixed_width > -1)
overflow = GTK_OVERFLOW_HIDDEN;
else
overflow = GTK_OVERFLOW_VISIBLE;
if (overflow != gtk_widget_get_overflow (GTK_WIDGET (self->header)))
{
GtkColumnViewCell *cell;
if (self->header)
gtk_widget_set_overflow (GTK_WIDGET (self->header), overflow);
for (cell = self->first_cell; cell; cell = gtk_column_view_cell_get_next (cell))
gtk_widget_set_overflow (GTK_WIDGET (cell), overflow);
}
gtk_column_view_column_queue_resize (self);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FIXED_WIDTH]);
}
/**
* gtk_column_view_column_get_fixed_width:
* @self: a #GtkColumnViewColumn
*
* Gets the fixed width of the column.
*
* Returns: the fixed with of the column
*/
int
gtk_column_view_column_get_fixed_width (GtkColumnViewColumn *self)
{
g_return_val_if_fail (GTK_IS_COLUMN_VIEW_COLUMN (self), -1);
return self->fixed_width;
}
GtkWidget *
gtk_column_view_column_get_header (GtkColumnViewColumn *self)
{
return self->header;
}
void
gtk_column_view_column_set_header_position (GtkColumnViewColumn *self,
int offset)
{
self->header_position = offset;
}
void
gtk_column_view_column_get_header_allocation (GtkColumnViewColumn *self,
int *offset,
int *size)
{
if (offset)
*offset = self->header_position;
if (size)
*size = self->allocation_size;
}
/**
* gtk_column_view_column_set_header_menu:
* @self: a #GtkColumnViewColumn
* @menu: (allow-none): a #GMenuModel, or %NULL
*
* Sets the menu model that is used to create the context menu
* for the column header.
*/
void
gtk_column_view_column_set_header_menu (GtkColumnViewColumn *self,
GMenuModel *menu)
{
g_return_if_fail (GTK_IS_COLUMN_VIEW_COLUMN (self));
g_return_if_fail (menu == NULL || G_IS_MENU_MODEL (menu));
if (!g_set_object (&self->menu, menu))
return;
if (self->header)
gtk_column_view_title_update (GTK_COLUMN_VIEW_TITLE (self->header));
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_HEADER_MENU]);
}
/**
* gtk_column_view_column_get_header_menu:
* @self: a #GtkColumnViewColumn
*
* Gets the menu model that is used to create the context menu
* for the column header.
*
* Returns: the #GMenuModel, or %NULL
*/
GMenuModel *
gtk_column_view_column_get_header_menu (GtkColumnViewColumn *self)
{
g_return_val_if_fail (GTK_IS_COLUMN_VIEW_COLUMN (self), NULL);
return self->menu;
}
+35
View File
@@ -72,6 +72,41 @@ void gtk_column_view_column_set_sorter (GtkColu
GDK_AVAILABLE_IN_ALL
GtkSorter * gtk_column_view_column_get_sorter (GtkColumnViewColumn *self);
GDK_AVAILABLE_IN_ALL
void gtk_column_view_column_set_visible (GtkColumnViewColumn *self,
gboolean visible);
GDK_AVAILABLE_IN_ALL
gboolean gtk_column_view_column_get_visible (GtkColumnViewColumn *self);
GDK_AVAILABLE_IN_ALL
void gtk_column_view_column_set_fixed_width (GtkColumnViewColumn *self,
int fixed_width);
GDK_AVAILABLE_IN_ALL
int gtk_column_view_column_get_fixed_width (GtkColumnViewColumn *self);
GDK_AVAILABLE_IN_ALL
void gtk_column_view_column_set_resizable (GtkColumnViewColumn *self,
gboolean resizable);
GDK_AVAILABLE_IN_ALL
gboolean gtk_column_view_column_get_resizable (GtkColumnViewColumn *self);
GDK_AVAILABLE_IN_ALL
void gtk_column_view_column_set_expand (GtkColumnViewColumn *self,
gboolean expand);
GDK_AVAILABLE_IN_ALL
gboolean gtk_column_view_column_get_expand (GtkColumnViewColumn *self);
GDK_AVAILABLE_IN_ALL
void gtk_column_view_column_set_reorderable (GtkColumnViewColumn *self,
gboolean reorderable);
GDK_AVAILABLE_IN_ALL
gboolean gtk_column_view_column_get_reorderable (GtkColumnViewColumn *self);
GDK_AVAILABLE_IN_ALL
void gtk_column_view_column_set_header_menu (GtkColumnViewColumn *self,
GMenuModel *menu);
GDK_AVAILABLE_IN_ALL
GMenuModel * gtk_column_view_column_get_header_menu (GtkColumnViewColumn *self);
G_END_DECLS
#endif /* __GTK_COLUMN_VIEW_COLUMN_H__ */
+9 -1
View File
@@ -33,6 +33,7 @@ void gtk_column_view_column_add_cell (GtkColu
void gtk_column_view_column_remove_cell (GtkColumnViewColumn *self,
GtkColumnViewCell *cell);
GtkColumnViewCell * gtk_column_view_column_get_first_cell (GtkColumnViewColumn *self);
GtkWidget * gtk_column_view_column_get_header (GtkColumnViewColumn *self);
void gtk_column_view_column_queue_resize (GtkColumnViewColumn *self);
void gtk_column_view_column_measure (GtkColumnViewColumn *self,
@@ -44,6 +45,13 @@ void gtk_column_view_column_allocate (GtkColu
void gtk_column_view_column_get_allocation (GtkColumnViewColumn *self,
int *offset,
int *size);
void gtk_column_view_column_active_sorter_changed (GtkColumnViewColumn *self);
void gtk_column_view_column_notify_sort (GtkColumnViewColumn *self);
void gtk_column_view_column_set_header_position (GtkColumnViewColumn *self,
int offset);
void gtk_column_view_column_get_header_allocation (GtkColumnViewColumn *self,
int *offset,
int *size);
#endif /* __GTK_COLUMN_VIEW_COLUMN_PRIVATE_H__ */
+8 -3
View File
@@ -118,11 +118,16 @@ gtk_column_view_layout_allocate (GtkLayoutManager *layout_manager,
int col_x, col_width;
if (GTK_IS_COLUMN_VIEW_CELL (child))
column = gtk_column_view_cell_get_column (GTK_COLUMN_VIEW_CELL (child));
{
column = gtk_column_view_cell_get_column (GTK_COLUMN_VIEW_CELL (child));
gtk_column_view_column_get_allocation (column, &col_x, &col_width);
}
else
column = gtk_column_view_title_get_column (GTK_COLUMN_VIEW_TITLE (child));
{
column = gtk_column_view_title_get_column (GTK_COLUMN_VIEW_TITLE (child));
gtk_column_view_column_get_header_allocation (column, &col_x, &col_width);
}
gtk_column_view_column_get_allocation (column, &col_x, &col_width);
gtk_widget_size_allocate (child, &(GtkAllocation) { col_x, 0, col_width, height }, baseline);
}
}
+3 -1
View File
@@ -21,14 +21,16 @@
#define __GTK_COLUMN_VIEW_PRIVATE_H__
#include "gtk/gtkcolumnview.h"
#include "gtk/gtklistview.h"
#include "gtk/gtkcolumnviewsorterprivate.h"
#include "gtk/gtklistitemwidgetprivate.h"
GtkListItemWidget * gtk_column_view_get_header_widget (GtkColumnView *self);
GtkListView * gtk_column_view_get_list_view (GtkColumnView *self);
void gtk_column_view_measure_across (GtkColumnView *self,
int *minimum,
int *natural);
void gtk_column_view_active_sorter_changed (GtkColumnView *self);
#endif /* __GTK_COLUMN_VIEW_PRIVATE_H__ */
+103 -36
View File
@@ -21,6 +21,7 @@
#include "gtkcolumnviewsorterprivate.h"
#include "gtkcolumnviewcolumnprivate.h"
#include "gtkintl.h"
#include "gtktypebuiltins.h"
@@ -47,45 +48,74 @@ struct _GtkColumnViewSorter
{
GtkSorter parent_instance;
GList *sorters;
GSequence *sorters;
};
G_DEFINE_TYPE (GtkColumnViewSorter, gtk_column_view_sorter, GTK_TYPE_SORTER)
static int
static GtkOrdering
gtk_column_view_sorter_compare (GtkSorter *sorter,
gpointer item1,
gpointer item2)
{
GtkColumnViewSorter *self = GTK_COLUMN_VIEW_SORTER (sorter);
int result = 0;
GList *l;
GtkOrdering result = GTK_ORDERING_EQUAL;
GSequenceIter *iter;
for (l = self->sorters; l; l = l->next)
for (iter = g_sequence_get_begin_iter (self->sorters);
!g_sequence_iter_is_end (iter);
iter = g_sequence_iter_next (iter))
{
Sorter *s = l->data;
GtkSorter *ss = gtk_column_view_column_get_sorter (s->column);
Sorter *s = g_sequence_get (iter);
result = gtk_sorter_compare (ss, item1, item2);
result = gtk_sorter_compare (s->sorter, item1, item2);
if (s->inverted)
result = - result;
if (result != 0)
if (result != GTK_ORDERING_EQUAL)
break;
}
return result;
}
static void changed_cb (GtkSorter *sorter, int change, gpointer data);
static GtkSorterOrder
gtk_column_view_sorter_get_order (GtkSorter *sorter)
{
GtkColumnViewSorter *self = GTK_COLUMN_VIEW_SORTER (sorter);
GtkSorterOrder result = GTK_SORTER_ORDER_NONE;
GSequenceIter *iter;
for (iter = g_sequence_get_begin_iter (self->sorters);
!g_sequence_iter_is_end (iter);
iter = g_sequence_iter_next (iter))
{
Sorter *s = g_sequence_get (iter);
switch (gtk_sorter_get_order (s->sorter))
{
case GTK_SORTER_ORDER_PARTIAL:
result = GTK_SORTER_ORDER_PARTIAL;
break;
case GTK_SORTER_ORDER_NONE:
break;
case GTK_SORTER_ORDER_TOTAL:
return GTK_SORTER_ORDER_TOTAL;
default:
g_assert_not_reached ();
break;
}
}
return result;
}
static void
gtk_column_view_sorter_dispose (GObject *object)
{
GtkColumnViewSorter *self = GTK_COLUMN_VIEW_SORTER (object);
g_list_free_full (self->sorters, free_sorter);
self->sorters = NULL;
g_clear_pointer (&self->sorters, g_sequence_free);
G_OBJECT_CLASS (gtk_column_view_sorter_parent_class)->dispose (object);
}
@@ -97,6 +127,7 @@ gtk_column_view_sorter_class_init (GtkColumnViewSorterClass *class)
GObjectClass *object_class = G_OBJECT_CLASS (class);
sorter_class->compare = gtk_column_view_sorter_compare;
sorter_class->get_order = gtk_column_view_sorter_get_order;
object_class->dispose = gtk_column_view_sorter_dispose;
}
@@ -104,6 +135,7 @@ gtk_column_view_sorter_class_init (GtkColumnViewSorterClass *class)
static void
gtk_column_view_sorter_init (GtkColumnViewSorter *self)
{
self->sorters = g_sequence_new (free_sorter);
}
GtkSorter *
@@ -113,7 +145,7 @@ gtk_column_view_sorter_new (void)
}
static void
changed_cb (GtkSorter *sorter, int change, gpointer data)
gtk_column_view_sorter_changed_cb (GtkSorter *sorter, int change, gpointer data)
{
gtk_sorter_changed (GTK_SORTER (data), GTK_SORTER_CHANGE_DIFFERENT);
}
@@ -122,16 +154,17 @@ static gboolean
remove_column (GtkColumnViewSorter *self,
GtkColumnViewColumn *column)
{
GList *l;
GSequenceIter *iter;
for (l = self->sorters; l; l = l->next)
for (iter = g_sequence_get_begin_iter (self->sorters);
!g_sequence_iter_is_end (iter);
iter = g_sequence_iter_next (iter))
{
Sorter *s = l->data;
Sorter *s = g_sequence_get (iter);
if (s->column == column)
{
self->sorters = g_list_remove_link (self->sorters, l);
free_sorter (s);
g_list_free (l);
g_sequence_remove (iter);
return TRUE;
}
}
@@ -143,8 +176,9 @@ gboolean
gtk_column_view_sorter_add_column (GtkColumnViewSorter *self,
GtkColumnViewColumn *column)
{
GSequenceIter *iter;
GtkSorter *sorter;
Sorter *s;
Sorter *s, *first;
g_return_val_if_fail (GTK_IS_COLUMN_VIEW_SORTER (self), FALSE);
g_return_val_if_fail (GTK_IS_COLUMN_VIEW_COLUMN (column), FALSE);
@@ -153,29 +187,38 @@ gtk_column_view_sorter_add_column (GtkColumnViewSorter *self,
if (sorter == NULL)
return FALSE;
if (self->sorters != NULL)
iter = g_sequence_get_begin_iter (self->sorters);
if (!g_sequence_iter_is_end (iter))
{
s = self->sorters->data;
if (s->column == column)
first = g_sequence_get (iter);
if (first->column == column)
{
s->inverted = !s->inverted;
first->inverted = !first->inverted;
goto out;
}
}
else
first = NULL;
remove_column (self, column);
s = g_new (Sorter, 1);
s->column = g_object_ref (column);
s->sorter = g_object_ref (sorter);
s->changed_id = g_signal_connect (sorter, "changed", G_CALLBACK (changed_cb), self);
s->changed_id = g_signal_connect (sorter, "changed", G_CALLBACK (gtk_column_view_sorter_changed_cb), self);
s->inverted = FALSE;
self->sorters = g_list_prepend (self->sorters, s);
g_sequence_insert_before (iter, s);
/* notify the previous first column to stop drawing an arrow */
if (first)
gtk_column_view_column_notify_sort (first->column);
out:
gtk_sorter_changed (GTK_SORTER (self), GTK_SORTER_CHANGE_DIFFERENT);
gtk_column_view_column_notify_sort (column);
return TRUE;
}
@@ -189,6 +232,7 @@ gtk_column_view_sorter_remove_column (GtkColumnViewSorter *self,
if (remove_column (self, column))
{
gtk_sorter_changed (GTK_SORTER (self), GTK_SORTER_CHANGE_DIFFERENT);
gtk_column_view_column_notify_sort (column);
return TRUE;
}
@@ -210,45 +254,68 @@ gtk_column_view_sorter_set_column (GtkColumnViewSorter *self,
if (sorter == NULL)
return FALSE;
g_list_free_full (self->sorters, free_sorter);
g_object_ref (column);
g_sequence_remove_range (g_sequence_get_begin_iter (self->sorters),
g_sequence_get_end_iter (self->sorters));
s = g_new (Sorter, 1);
s->column = g_object_ref (column);
s->sorter = g_object_ref (sorter);
s->changed_id = g_signal_connect (sorter, "changed", G_CALLBACK (changed_cb), self);
s->changed_id = g_signal_connect (sorter, "changed", G_CALLBACK (gtk_column_view_sorter_changed_cb), self);
s->inverted = inverted;
self->sorters = g_list_prepend (self->sorters, s);
g_sequence_prepend (self->sorters, s);
gtk_sorter_changed (GTK_SORTER (self), GTK_SORTER_CHANGE_DIFFERENT);
gtk_column_view_column_notify_sort (column);
g_object_unref (column);
return TRUE;
}
void
gtk_column_view_sorter_reset (GtkColumnViewSorter *self)
gtk_column_view_sorter_clear (GtkColumnViewSorter *self)
{
GSequenceIter *iter;
Sorter *s;
GtkColumnViewColumn *column;
g_return_if_fail (GTK_IS_COLUMN_VIEW_SORTER (self));
if (self->sorters == NULL)
if (g_sequence_is_empty (self->sorters))
return;
g_list_free_full (self->sorters, free_sorter);
iter = g_sequence_get_begin_iter (self->sorters);
s = g_sequence_get (iter);
column = g_object_ref (s->column);
g_sequence_remove_range (iter, g_sequence_get_end_iter (self->sorters));
gtk_sorter_changed (GTK_SORTER (self), GTK_SORTER_CHANGE_DIFFERENT);
gtk_column_view_column_notify_sort (column);
g_object_unref (column);
}
GtkColumnViewColumn *
gtk_column_view_sorter_get_active (GtkColumnViewSorter *self,
gboolean *inverted)
gtk_column_view_sorter_get_sort_column (GtkColumnViewSorter *self,
gboolean *inverted)
{
GSequenceIter *iter;
Sorter *s;
g_return_val_if_fail (GTK_IS_COLUMN_VIEW_SORTER (self), NULL);
if (self->sorters == NULL)
if (g_sequence_is_empty (self->sorters))
return NULL;
s = self->sorters->data;
iter = g_sequence_get_begin_iter (self->sorters);
s = g_sequence_get (iter);
*inverted = s->inverted;
+8 -9
View File
@@ -34,18 +34,17 @@ G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE (GtkColumnViewSorter, gtk_column_view_sorter, GTK, COLUMN_VIEW_SORTER, GtkSorter)
GtkSorter * gtk_column_view_sorter_new (void);
GtkSorter * gtk_column_view_sorter_new (void);
gboolean gtk_column_view_sorter_add_column (GtkColumnViewSorter *self,
GtkColumnViewColumn *column);
gboolean gtk_column_view_sorter_remove_column (GtkColumnViewSorter *self,
GtkColumnViewColumn *column);
gboolean gtk_column_view_sorter_add_column (GtkColumnViewSorter *self,
GtkColumnViewColumn *column);
gboolean gtk_column_view_sorter_remove_column (GtkColumnViewSorter *self,
GtkColumnViewColumn *column);
void gtk_column_view_sorter_reset (GtkColumnViewSorter *self);
void gtk_column_view_sorter_clear (GtkColumnViewSorter *self);
GtkColumnViewColumn *
gtk_column_view_sorter_get_active (GtkColumnViewSorter *self,
gboolean *inverted);
GtkColumnViewColumn * gtk_column_view_sorter_get_sort_column (GtkColumnViewSorter *self,
gboolean *inverted);
gboolean gtk_column_view_sorter_set_column (GtkColumnViewSorter *self,
GtkColumnViewColumn *column,
+73 -9
View File
@@ -30,6 +30,8 @@
#include "gtkbox.h"
#include "gtkimage.h"
#include "gtkgestureclick.h"
#include "gtkpopovermenu.h"
#include "gtknative.h"
struct _GtkColumnViewTitle
{
@@ -40,6 +42,7 @@ struct _GtkColumnViewTitle
GtkWidget *box;
GtkWidget *title;
GtkWidget *sort;
GtkWidget *popup_menu;
};
struct _GtkColumnViewTitleClass
@@ -58,10 +61,18 @@ gtk_column_view_title_measure (GtkWidget *widget,
int *minimum_baseline,
int *natural_baseline)
{
GtkColumnViewTitle *self = GTK_COLUMN_VIEW_TITLE (widget);
GtkWidget *child = gtk_widget_get_first_child (widget);
if (child)
gtk_widget_measure (child, orientation, for_size, minimum, natural, minimum_baseline, natural_baseline);
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
int fixed_width = gtk_column_view_column_get_fixed_width (self->column);
if (fixed_width > -1)
*minimum = *natural = fixed_width;
}
}
static void
@@ -70,10 +81,14 @@ gtk_column_view_title_size_allocate (GtkWidget *widget,
int height,
int baseline)
{
GtkColumnViewTitle *self = GTK_COLUMN_VIEW_TITLE (widget);
GtkWidget *child = gtk_widget_get_first_child (widget);
if (child)
gtk_widget_allocate (child, width, height, baseline, NULL);
if (self->popup_menu)
gtk_native_check_resize (GTK_NATIVE (self->popup_menu));
}
static void
@@ -82,6 +97,7 @@ gtk_column_view_title_dispose (GObject *object)
GtkColumnViewTitle *self = GTK_COLUMN_VIEW_TITLE (object);
g_clear_pointer (&self->box, gtk_widget_unparent);
g_clear_pointer (&self->popup_menu, gtk_widget_unparent);
g_clear_object (&self->column);
@@ -112,13 +128,8 @@ gtk_column_view_title_resize_func (GtkWidget *widget)
}
static void
click_pressed_cb (GtkGestureClick *gesture,
guint n_press,
gdouble x,
gdouble y,
GtkWidget *widget)
activate_sort (GtkColumnViewTitle *self)
{
GtkColumnViewTitle *self = GTK_COLUMN_VIEW_TITLE (widget);
GtkSorter *sorter;
GtkColumnView *view;
GtkColumnViewSorter *view_sorter;
@@ -130,7 +141,57 @@ click_pressed_cb (GtkGestureClick *gesture,
view = gtk_column_view_column_get_column_view (self->column);
view_sorter = GTK_COLUMN_VIEW_SORTER (gtk_column_view_get_sorter (view));
gtk_column_view_sorter_add_column (view_sorter, self->column);
gtk_column_view_active_sorter_changed (view);
}
static void
show_menu (GtkColumnViewTitle *self,
double x,
double y)
{
g_print ("show menu\n");
if (!self->popup_menu)
{
GMenuModel *model;
model = gtk_column_view_column_get_header_menu (self->column);
if (!model)
return;
g_print ("got a model\n");
self->popup_menu = gtk_popover_menu_new_from_model (GTK_WIDGET (self), model);
gtk_popover_set_position (GTK_POPOVER (self->popup_menu), GTK_POS_BOTTOM);
gtk_popover_set_has_arrow (GTK_POPOVER (self->popup_menu), FALSE);
gtk_widget_set_halign (self->popup_menu, GTK_ALIGN_START);
}
if (x != -1 && y != -1)
{
GdkRectangle rect = { x, y, 1, 1 };
gtk_popover_set_pointing_to (GTK_POPOVER (self->popup_menu), &rect);
}
else
gtk_popover_set_pointing_to (GTK_POPOVER (self->popup_menu), NULL);
gtk_popover_popup (GTK_POPOVER (self->popup_menu));
}
static void
click_released_cb (GtkGestureClick *gesture,
guint n_press,
double x,
double y,
GtkWidget *widget)
{
GtkColumnViewTitle *self = GTK_COLUMN_VIEW_TITLE (widget);
guint button;
button = gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (gesture));
if (button == GDK_BUTTON_PRIMARY)
activate_sort (self);
else if (button == GDK_BUTTON_SECONDARY)
show_menu (self, x, y);
}
static void
@@ -151,7 +212,8 @@ gtk_column_view_title_init (GtkColumnViewTitle *self)
gtk_container_add (GTK_CONTAINER (self->box), self->sort);
gesture = gtk_gesture_click_new ();
g_signal_connect (gesture, "pressed", G_CALLBACK (click_pressed_cb), self);
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (gesture), 0);
g_signal_connect (gesture, "released", G_CALLBACK (click_released_cb), self);
gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (gesture));
}
@@ -185,7 +247,7 @@ gtk_column_view_title_update (GtkColumnViewTitle *self)
{
view = gtk_column_view_column_get_column_view (self->column);
view_sorter = GTK_COLUMN_VIEW_SORTER (gtk_column_view_get_sorter (view));
active = gtk_column_view_sorter_get_active (view_sorter, &inverted);
active = gtk_column_view_sorter_get_sort_column (view_sorter, &inverted);
gtk_widget_show (self->sort);
if (self->column == active)
@@ -200,6 +262,8 @@ gtk_column_view_title_update (GtkColumnViewTitle *self)
}
else
gtk_widget_hide (self->sort);
g_clear_pointer (&self->popup_menu, gtk_widget_unparent);
}
GtkColumnViewColumn *
+157
View File
@@ -0,0 +1,157 @@
/*
* 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 "gtkcustomfilter.h"
#include "gtkintl.h"
#include "gtktypebuiltins.h"
/**
* SECTION:gtkcustomfilter
* @Title: GtkCustomFilter
* @Short_description: Filtering with callbacks
*
* #GtkCustomFilter is a #GtkFilter that uses a callback to determine whether
* to include an item or not.
*/
struct _GtkCustomFilter
{
GtkFilter parent_instance;
GtkCustomFilterFunc match_func;
gpointer user_data;
GDestroyNotify user_destroy;
};
G_DEFINE_TYPE (GtkCustomFilter, gtk_custom_filter, GTK_TYPE_FILTER)
static gboolean
gtk_custom_filter_match (GtkFilter *filter,
gpointer item)
{
GtkCustomFilter *self = GTK_CUSTOM_FILTER (filter);
if (!self->match_func)
return TRUE;
return self->match_func (item, self->user_data);
}
static GtkFilterMatch
gtk_custom_filter_get_strictness (GtkFilter *filter)
{
GtkCustomFilter *self = GTK_CUSTOM_FILTER (filter);
if (!self->match_func)
return GTK_FILTER_MATCH_ALL;
return GTK_FILTER_MATCH_SOME;
}
static void
gtk_custom_filter_dispose (GObject *object)
{
GtkCustomFilter *self = GTK_CUSTOM_FILTER (object);
if (self->user_destroy)
self->user_destroy (self->user_data);
G_OBJECT_CLASS (gtk_custom_filter_parent_class)->dispose (object);
}
static void
gtk_custom_filter_class_init (GtkCustomFilterClass *class)
{
GtkFilterClass *filter_class = GTK_FILTER_CLASS (class);
GObjectClass *object_class = G_OBJECT_CLASS (class);
filter_class->match = gtk_custom_filter_match;
filter_class->get_strictness = gtk_custom_filter_get_strictness;
object_class->dispose = gtk_custom_filter_dispose;
}
static void
gtk_custom_filter_init (GtkCustomFilter *self)
{
}
/**
* gtk_custom_filter_new:
* @match_func: (nullable): function to filter items
* @user_data: (nullable): user data to pass to @match_func
* @user_destroy: destory notify
*
* Creates a new filter using the given @match_func to filter
* items.
*
* If the filter func changes its filtering behavior,
* gtk_filter_changed() needs to be called.
*
* Returns: a new #GtkFilter
**/
GtkFilter *
gtk_custom_filter_new (GtkCustomFilterFunc match_func,
gpointer user_data,
GDestroyNotify user_destroy)
{
GtkCustomFilter *result;
result = g_object_new (GTK_TYPE_CUSTOM_FILTER, NULL);
gtk_custom_filter_set_filter_func (result, match_func, user_data, user_destroy);
return GTK_FILTER (result);
}
/**
* gtk_custom_filter_set_filter_func:
* @self: a #GtkCustomFilter
* @match_func: (nullable): function to filter items
* @user_data: (nullable): user data to pass to @match_func
* @user_destroy: destory notify
*
* Sets (or unsets) the function used for filtering items.
*
* If the filter func changes its filtering behavior,
* gtk_filter_changed() needs to be called.
*
* If a previous function was set, its @user_destroy will be
* called now.
**/
void
gtk_custom_filter_set_filter_func (GtkCustomFilter *self,
GtkCustomFilterFunc match_func,
gpointer user_data,
GDestroyNotify user_destroy)
{
g_return_if_fail (GTK_IS_CUSTOM_FILTER (self));
g_return_if_fail (match_func || (user_data == NULL && !user_destroy));
if (self->user_destroy)
self->user_destroy (self->user_data);
self->match_func = match_func;
self->user_data = user_data;
self->user_destroy = user_destroy;
gtk_filter_changed (GTK_FILTER (self), GTK_FILTER_CHANGE_DIFFERENT);
}
+8 -17
View File
@@ -17,8 +17,8 @@
* Authors: Benjamin Otte <otte@gnome.org>
*/
#ifndef __GTK_FILTERS_H__
#define __GTK_FILTERS_H__
#ifndef __GTK_CUSTOM_FILTER_H__
#define __GTK_CUSTOM_FILTER_H__
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gtk/gtk.h> can be included directly."
@@ -45,25 +45,16 @@ typedef gboolean (* GtkCustomFilterFunc) (gpointer item, gpointer user_data);
GDK_AVAILABLE_IN_ALL
G_DECLARE_FINAL_TYPE (GtkCustomFilter, gtk_custom_filter, GTK, CUSTOM_FILTER, GtkFilter)
GDK_AVAILABLE_IN_ALL
GtkFilter * gtk_custom_filter_new (GtkCustomFilterFunc filter_func,
GtkFilter * gtk_custom_filter_new (GtkCustomFilterFunc match_func,
gpointer user_data,
GDestroyNotify user_destroy);
#define GTK_TYPE_ANY_FILTER (gtk_any_filter_get_type ())
GDK_AVAILABLE_IN_ALL
G_DECLARE_FINAL_TYPE (GtkAnyFilter, gtk_any_filter, GTK, ANY_FILTER, GtkFilter)
GDK_AVAILABLE_IN_ALL
GtkFilter * gtk_any_filter_new (void);
GDK_AVAILABLE_IN_ALL
void gtk_any_filter_append (GtkAnyFilter *self,
GtkFilter *filter);
GDK_AVAILABLE_IN_ALL
void gtk_any_filter_remove (GtkAnyFilter *self,
guint position);
void gtk_custom_filter_set_filter_func (GtkCustomFilter *self,
GtkCustomFilterFunc match_func,
gpointer user_data,
GDestroyNotify user_destroy);
G_END_DECLS
#endif /* __GTK_FILTERS_H__ */
#endif /* __GTK_CUSTOM_FILTER_H__ */
+56 -5
View File
@@ -43,14 +43,28 @@ struct _GtkCustomSorter
G_DEFINE_TYPE (GtkCustomSorter, gtk_custom_sorter, GTK_TYPE_SORTER)
static int
static GtkOrdering
gtk_custom_sorter_compare (GtkSorter *sorter,
gpointer item1,
gpointer item2)
{
GtkCustomSorter *self = GTK_CUSTOM_SORTER (sorter);
return self->sort_func (item1, item2, self->user_data);
if (!self->sort_func)
return GTK_ORDERING_EQUAL;
return gtk_ordering_from_cmpfunc (self->sort_func (item1, item2, self->user_data));
}
static GtkSorterOrder
gtk_custom_sorter_get_order (GtkSorter *sorter)
{
GtkCustomSorter *self = GTK_CUSTOM_SORTER (sorter);
if (!self->sort_func)
return GTK_SORTER_ORDER_NONE;
return GTK_SORTER_ORDER_PARTIAL;
}
static void
@@ -61,6 +75,10 @@ gtk_custom_sorter_dispose (GObject *object)
if (self->user_destroy)
self->user_destroy (self->user_data);
self->sort_func = NULL;
self->user_destroy = NULL;
self->user_data = NULL;
G_OBJECT_CLASS (gtk_custom_sorter_parent_class)->dispose (object);
}
@@ -71,6 +89,7 @@ gtk_custom_sorter_class_init (GtkCustomSorterClass *class)
GObjectClass *object_class = G_OBJECT_CLASS (class);
sorter_class->compare = gtk_custom_sorter_compare;
sorter_class->get_order = gtk_custom_sorter_get_order;
object_class->dispose = gtk_custom_sorter_dispose;
}
@@ -100,9 +119,41 @@ gtk_custom_sorter_new (GCompareDataFunc sort_func,
sorter = g_object_new (GTK_TYPE_CUSTOM_SORTER, NULL);
sorter->sort_func = sort_func;
sorter->user_data = user_data;
sorter->user_destroy = user_destroy;
gtk_custom_sorter_set_sort_func (sorter, sort_func, user_data, user_destroy);
return GTK_SORTER (sorter);
}
/**
* gtk_custom_sorter_set_sort_func:
* @self: a #GtkCustomSorter
* @sort_func: (nullable): function to sort items
* @user_data: (nullable): user data to pass to @match_func
* @user_destroy: destory notify
*
* Sets (or unsets) the function used for sorting items.
*
* If the sort func changes its sorting behavior,
* gtk_sorter_changed() needs to be called.
*
* If a previous function was set, its @user_destroy will be
* called now.
**/
void
gtk_custom_sorter_set_sort_func (GtkCustomSorter *self,
GCompareDataFunc sort_func,
gpointer user_data,
GDestroyNotify user_destroy)
{
g_return_if_fail (GTK_IS_CUSTOM_SORTER (self));
g_return_if_fail (sort_func || (user_data == NULL && !user_destroy));
if (self->user_destroy)
self->user_destroy (self->user_data);
self->sort_func = sort_func;
self->user_data = user_data;
self->user_destroy = user_destroy;
gtk_sorter_changed (GTK_SORTER (self), GTK_SORTER_CHANGE_DIFFERENT);
}
+9 -3
View File
@@ -34,9 +34,15 @@ GDK_AVAILABLE_IN_ALL
G_DECLARE_FINAL_TYPE (GtkCustomSorter, gtk_custom_sorter, GTK, CUSTOM_SORTER, GtkSorter)
GDK_AVAILABLE_IN_ALL
GtkSorter * gtk_custom_sorter_new (GCompareDataFunc sort_func,
gpointer user_data,
GDestroyNotify user_destroy);
GtkSorter * gtk_custom_sorter_new (GCompareDataFunc sort_func,
gpointer user_data,
GDestroyNotify user_destroy);
GDK_AVAILABLE_IN_ALL
void gtk_custom_sorter_set_sort_func (GtkCustomSorter *self,
GCompareDataFunc sort_func,
gpointer user_data,
GDestroyNotify user_destroy);
G_END_DECLS
+784 -46
View File
File diff suppressed because it is too large Load Diff
+29 -6
View File
@@ -21,6 +21,7 @@
#define __GTK_DROP_DOWN_H__
#include <gtk/gtkwidget.h>
#include <gtk/gtkexpression.h>
G_BEGIN_DECLS
@@ -31,14 +32,23 @@ G_DECLARE_FINAL_TYPE (GtkDropDown, gtk_drop_down, GTK, DROP_DOWN, GtkWidget)
GDK_AVAILABLE_IN_ALL
GtkWidget * gtk_drop_down_new (void);
GDK_AVAILABLE_IN_ALL
GtkWidget * gtk_drop_down_new_with_factory (GtkListItemFactory *factory);
GDK_AVAILABLE_IN_ALL
GListModel * gtk_drop_down_get_model (GtkDropDown *self);
void gtk_drop_down_set_from_strings (GtkDropDown *self,
const char *const *texts);
GDK_AVAILABLE_IN_ALL
void gtk_drop_down_set_model (GtkDropDown *self,
GListModel *model);
GDK_AVAILABLE_IN_ALL
GListModel * gtk_drop_down_get_model (GtkDropDown *self);
GDK_AVAILABLE_IN_ALL
void gtk_drop_down_set_selected (GtkDropDown *self,
guint position);
GDK_AVAILABLE_IN_ALL
guint gtk_drop_down_get_selected (GtkDropDown *self);
GDK_AVAILABLE_IN_ALL
void gtk_drop_down_set_factory (GtkDropDown *self,
GtkListItemFactory *factory);
@@ -47,10 +57,23 @@ GtkListItemFactory *
gtk_drop_down_get_factory (GtkDropDown *self);
GDK_AVAILABLE_IN_ALL
void gtk_drop_down_set_selected (GtkDropDown *self,
guint position);
void gtk_drop_down_set_list_factory (GtkDropDown *self,
GtkListItemFactory *factory);
GDK_AVAILABLE_IN_ALL
guint gtk_drop_down_get_selected (GtkDropDown *self);
GtkListItemFactory *
gtk_drop_down_get_list_factory (GtkDropDown *self);
GDK_AVAILABLE_IN_ALL
void gtk_drop_down_set_expression (GtkDropDown *self,
GtkExpression *expression);
GDK_AVAILABLE_IN_ALL
GtkExpression * gtk_drop_down_get_expression (GtkDropDown *self);
GDK_AVAILABLE_IN_ALL
void gtk_drop_down_set_enable_search (GtkDropDown *self,
gboolean enable_search);
GDK_AVAILABLE_IN_ALL
gboolean gtk_drop_down_get_enable_search (GtkDropDown *self);
G_END_DECLS
+36 -1
View File
@@ -607,6 +607,39 @@ typedef enum
GTK_NUMBER_UP_LAYOUT_BOTTOM_TO_TOP_RIGHT_TO_LEFT /*< nick=btrl >*/
} GtkNumberUpLayout;
/**
* GtkOrdering:
* @GTK_ORDERING_SMALLER: the first value is smaller than the second
* @GTK_ORDERING_EQUAL: the two values are equal
* @GTK_ORDERING_LARGER: the first value is larger than the second
*
* Describes the way two values can be compared.
*
* These values can be used with a #GCompareFunc. However, a
* #GCompareFunc is allowed to return any integer values.
* For converting such a value to a #GtkOrdering, use
* gtk_ordering_from_cmpfunc().
*/
typedef enum {
GTK_ORDERING_SMALLER = -1,
GTK_ORDERING_EQUAL = 0,
GTK_ORDERING_LARGER = 1
} GtkOrdering;
/**
* gtk_ordering_from_cmpfunc:
* @cmpfunc_result: Result of a comparison function
*
* Converts the result of a #GCompareFunc like strcmp() to a #GtkOrdering.
*
* Returns: the corresponding #GtkOrdering
**/
static inline GtkOrdering
gtk_ordering_from_cmpfunc (int cmpfunc_result)
{
return (GtkOrdering) ((cmpfunc_result > 0) - (cmpfunc_result < 0));
}
/**
* GtkPageOrientation:
* @GTK_PAGE_ORIENTATION_PORTRAIT: Portrait mode.
@@ -862,6 +895,7 @@ G_END_DECLS
* @GTK_INPUT_PURPOSE_NAME: Edited field expects the name of a person
* @GTK_INPUT_PURPOSE_PASSWORD: Like @GTK_INPUT_PURPOSE_FREE_FORM, but characters are hidden
* @GTK_INPUT_PURPOSE_PIN: Like @GTK_INPUT_PURPOSE_DIGITS, but characters are hidden
* @GTK_INPUT_PURPOSE_TERMINAL: Allow any character, in addition to control codes
*
* Describes primary purpose of the input widget. This information is
* useful for on-screen keyboards and similar input methods to decide
@@ -893,7 +927,8 @@ typedef enum
GTK_INPUT_PURPOSE_EMAIL,
GTK_INPUT_PURPOSE_NAME,
GTK_INPUT_PURPOSE_PASSWORD,
GTK_INPUT_PURPOSE_PIN
GTK_INPUT_PURPOSE_PIN,
GTK_INPUT_PURPOSE_TERMINAL,
} GtkInputPurpose;
/**
+1 -10
View File
@@ -24,8 +24,6 @@
#error "Only <gtk/gtk.h> can be included directly."
#endif
typedef struct _GtkEventControllerClass GtkEventControllerClass;
#include <gdk/gdk.h>
#include <gtk/gtktypes.h>
#include <gtk/gtkenums.h>
@@ -33,15 +31,8 @@ typedef struct _GtkEventControllerClass GtkEventControllerClass;
G_BEGIN_DECLS
#define GTK_TYPE_EVENT_CONTROLLER (gtk_event_controller_get_type ())
#define GTK_EVENT_CONTROLLER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_EVENT_CONTROLLER, GtkEventController))
#define GTK_EVENT_CONTROLLER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GTK_TYPE_EVENT_CONTROLLER, GtkEventControllerClass))
#define GTK_IS_EVENT_CONTROLLER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_EVENT_CONTROLLER))
#define GTK_IS_EVENT_CONTROLLER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_TYPE_EVENT_CONTROLLER))
#define GTK_EVENT_CONTROLLER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_EVENT_CONTROLLER, GtkEventControllerClass))
GDK_AVAILABLE_IN_ALL
GType gtk_event_controller_get_type (void) G_GNUC_CONST;
GDK_DECLARE_EXPORTED_TYPE (GtkEventController, gtk_event_controller, GTK, EVENT_CONTROLLER)
GDK_AVAILABLE_IN_ALL
GtkWidget * gtk_event_controller_get_widget (GtkEventController *controller);
+1 -10
View File
@@ -31,17 +31,8 @@
G_BEGIN_DECLS
#define GTK_TYPE_EVENT_CONTROLLER_KEY (gtk_event_controller_key_get_type ())
#define GTK_EVENT_CONTROLLER_KEY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_EVENT_CONTROLLER_KEY, GtkEventControllerKey))
#define GTK_EVENT_CONTROLLER_KEY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GTK_TYPE_EVENT_CONTROLLER_KEY, GtkEventControllerKeyClass))
#define GTK_IS_EVENT_CONTROLLER_KEY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_EVENT_CONTROLLER_KEY))
#define GTK_IS_EVENT_CONTROLLER_KEY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_TYPE_EVENT_CONTROLLER_KEY))
#define GTK_EVENT_CONTROLLER_KEY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_EVENT_CONTROLLER_KEY, GtkEventControllerKeyClass))
typedef struct _GtkEventControllerKey GtkEventControllerKey;
typedef struct _GtkEventControllerKeyClass GtkEventControllerKeyClass;
GDK_AVAILABLE_IN_ALL
GType gtk_event_controller_key_get_type (void) G_GNUC_CONST;
GDK_DECLARE_EXPORTED_TYPE (GtkEventControllerKey, gtk_event_controller_key, GTK, EVENT_CONTROLLER_KEY)
GDK_AVAILABLE_IN_ALL
GtkEventController *gtk_event_controller_key_new (void);
+1 -10
View File
@@ -29,17 +29,8 @@
G_BEGIN_DECLS
#define GTK_TYPE_EVENT_CONTROLLER_LEGACY (gtk_event_controller_legacy_get_type ())
#define GTK_EVENT_CONTROLLER_LEGACY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_EVENT_CONTROLLER_LEGACY, GtkEventControllerLegacy))
#define GTK_EVENT_CONTROLLER_LEGACY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GTK_TYPE_EVENT_CONTROLLER_LEGACY, GtkEventControllerLegacyClass))
#define GTK_IS_EVENT_CONTROLLER_LEGACY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_EVENT_CONTROLLER_LEGACY))
#define GTK_IS_EVENT_CONTROLLER_LEGACY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_TYPE_EVENT_CONTROLLER_LEGACY))
#define GTK_EVENT_CONTROLLER_LEGACY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_EVENT_CONTROLLER_LEGACY, GtkEventControllerLegacyClass))
typedef struct _GtkEventControllerLegacy GtkEventControllerLegacy;
typedef struct _GtkEventControllerLegacyClass GtkEventControllerLegacyClass;
GDK_AVAILABLE_IN_ALL
GType gtk_event_controller_legacy_get_type (void) G_GNUC_CONST;
GDK_DECLARE_EXPORTED_TYPE (GtkEventControllerLegacy, gtk_event_controller_legacy, GTK, EVENT_CONTROLLER_LEGACY)
GDK_AVAILABLE_IN_ALL
GtkEventController *gtk_event_controller_legacy_new (void);
+60 -29
View File
@@ -43,8 +43,8 @@ struct _GtkEventControllerMotion
const GdkEvent *current_event;
guint is_pointer_focus : 1;
guint contains_pointer_focus : 1;
guint is_pointer : 1;
guint contains_pointer : 1;
};
struct _GtkEventControllerMotionClass
@@ -60,8 +60,8 @@ enum {
};
enum {
PROP_IS_POINTER_FOCUS = 1,
PROP_CONTAINS_POINTER_FOCUS,
PROP_IS_POINTER = 1,
PROP_CONTAINS_POINTER,
NUM_PROPERTIES
};
@@ -89,11 +89,11 @@ update_pointer_focus (GtkEventControllerMotion *motion,
case GDK_NOTIFY_ANCESTOR:
case GDK_NOTIFY_NONLINEAR:
is_pointer = enter;
contains_pointer = FALSE;
contains_pointer = enter;
break;
case GDK_NOTIFY_INFERIOR:
is_pointer = enter;
contains_pointer = !enter;
contains_pointer = TRUE;
break;
case GDK_NOTIFY_UNKNOWN:
default:
@@ -102,15 +102,15 @@ update_pointer_focus (GtkEventControllerMotion *motion,
}
g_object_freeze_notify (G_OBJECT (motion));
if (motion->is_pointer_focus != is_pointer)
if (motion->is_pointer != is_pointer)
{
motion->is_pointer_focus = is_pointer;
g_object_notify (G_OBJECT (motion), "is-pointer-focus");
motion->is_pointer = is_pointer;
g_object_notify (G_OBJECT (motion), "is-pointer");
}
if (motion->contains_pointer_focus != contains_pointer)
if (motion->contains_pointer != contains_pointer)
{
motion->contains_pointer_focus = contains_pointer;
g_object_notify (G_OBJECT (motion), "contains-pointer-focus");
motion->contains_pointer = contains_pointer;
g_object_notify (G_OBJECT (motion), "contains-pointer");
}
g_object_thaw_notify (G_OBJECT (motion));
}
@@ -182,12 +182,12 @@ gtk_event_controller_motion_get_property (GObject *object,
switch (prop_id)
{
case PROP_IS_POINTER_FOCUS:
g_value_set_boolean (value, controller->is_pointer_focus);
case PROP_IS_POINTER:
g_value_set_boolean (value, controller->is_pointer);
break;
case PROP_CONTAINS_POINTER_FOCUS:
g_value_set_boolean (value, controller->contains_pointer_focus);
case PROP_CONTAINS_POINTER:
g_value_set_boolean (value, controller->contains_pointer);
break;
default:
@@ -206,37 +206,37 @@ gtk_event_controller_motion_class_init (GtkEventControllerMotionClass *klass)
controller_class->handle_event = gtk_event_controller_motion_handle_event;
/**
* GtkEventControllerMotion:is-pointer-focus:
* GtkEventControllerMotion:is-pointer:
*
* Whether the pointer is in the controllers widget itself,
* as opposed to in a descendent widget. See
* #GtkEventControllerMotion:contains-pointer-focus.
* as opposed to in a descendent widget. See also
* #GtkEventControllerMotion:contains-pointer.
*
* When handling crossing events, this property is updated
* before #GtkEventControllerMotion::enter or
* #GtkEventControllerMotion::leave are emitted.
*/
props[PROP_IS_POINTER_FOCUS] =
g_param_spec_boolean ("is-pointer-focus",
P_("Is Pointer Focus"),
props[PROP_IS_POINTER] =
g_param_spec_boolean ("is-pointer",
P_("Is Pointer"),
P_("Whether the pointer is in the controllers widget"),
FALSE,
G_PARAM_READABLE);
/**
* GtkEventControllerMotion:contains-pointer-focus:
* GtkEventControllerMotion:contains-pointer:
*
* Whether the pointer is in a descendant of the controllers widget.
* See #GtkEventControllerMotion:is-pointer-focus.
* Whether the pointer is in the controllers widget or a descendant.
* See also #GtkEventControllerMotion:is-pointer.
*
* When handling crossing events, this property is updated
* before #GtkEventControllerMotion::enter or
* #GtkEventControllerMotion::leave are emitted.
*/
props[PROP_CONTAINS_POINTER_FOCUS] =
g_param_spec_boolean ("contains-pointer-focus",
P_("Contains Pointer Focus"),
P_("Whether the pointer is in a descendant of the controllers widget"),
props[PROP_CONTAINS_POINTER] =
g_param_spec_boolean ("contains-pointer",
P_("Contains Pointer"),
P_("Whether the pointer is inthe controllers widget or a descendant"),
FALSE,
G_PARAM_READABLE);
@@ -381,3 +381,34 @@ gtk_event_controller_motion_get_pointer_target (GtkEventControllerMotion *contro
return (GtkWidget *)gdk_event_get_related_target (controller->current_event);
}
/**
* gtk_event_controller_motion_contains_pointer:
* @self: a #GtkEventControllerMotion
*
* Returns the value of the GtkEventControllerMotion:contains-pointer property.
*
* Returns: %TRUE if a pointer is within @self or one of its children
*/
gboolean
gtk_event_controller_motion_contains_pointer (GtkEventControllerMotion *self)
{
g_return_val_if_fail (GTK_IS_EVENT_CONTROLLER_MOTION (self), FALSE);
return self->contains_pointer;
}
/**
* gtk_event_controller_motion_is_pointer:
* @self: a #GtkEventControllerKey
*
* Returns the value of the GtkEventControllerMotion:is-pointer property.
*
* Returns: %TRUE if a pointer is within @self but not one of its children
*/
gboolean
gtk_event_controller_motion_is_pointer (GtkEventControllerMotion *self)
{
g_return_val_if_fail (GTK_IS_EVENT_CONTROLLER_MOTION (self), FALSE);
return self->is_pointer;
}
+6 -10
View File
@@ -30,17 +30,8 @@
G_BEGIN_DECLS
#define GTK_TYPE_EVENT_CONTROLLER_MOTION (gtk_event_controller_motion_get_type ())
#define GTK_EVENT_CONTROLLER_MOTION(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_EVENT_CONTROLLER_MOTION, GtkEventControllerMotion))
#define GTK_EVENT_CONTROLLER_MOTION_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GTK_TYPE_EVENT_CONTROLLER_MOTION, GtkEventControllerMotionClass))
#define GTK_IS_EVENT_CONTROLLER_MOTION(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_EVENT_CONTROLLER_MOTION))
#define GTK_IS_EVENT_CONTROLLER_MOTION_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_TYPE_EVENT_CONTROLLER_MOTION))
#define GTK_EVENT_CONTROLLER_MOTION_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_EVENT_CONTROLLER_MOTION, GtkEventControllerMotionClass))
typedef struct _GtkEventControllerMotion GtkEventControllerMotion;
typedef struct _GtkEventControllerMotionClass GtkEventControllerMotionClass;
GDK_AVAILABLE_IN_ALL
GType gtk_event_controller_motion_get_type (void) G_GNUC_CONST;
GDK_DECLARE_EXPORTED_TYPE (GtkEventControllerMotion, gtk_event_controller_motion, GTK, EVENT_CONTROLLER_MOTION)
GDK_AVAILABLE_IN_ALL
GtkEventController *gtk_event_controller_motion_new (void);
@@ -50,6 +41,11 @@ GtkWidget * gtk_event_controller_motion_get_pointer_origin (GtkEventCont
GDK_AVAILABLE_IN_ALL
GtkWidget * gtk_event_controller_motion_get_pointer_target (GtkEventControllerMotion *controller);
GDK_AVAILABLE_IN_ALL
gboolean gtk_event_controller_motion_contains_pointer (GtkEventControllerMotion *self);
GDK_AVAILABLE_IN_ALL
gboolean gtk_event_controller_motion_is_pointer (GtkEventControllerMotion *self);
G_END_DECLS
#endif /* __GTK_EVENT_CONTROLLER_MOTION_H__ */
+2 -11
View File
@@ -30,14 +30,8 @@
G_BEGIN_DECLS
#define GTK_TYPE_EVENT_CONTROLLER_SCROLL (gtk_event_controller_scroll_get_type ())
#define GTK_EVENT_CONTROLLER_SCROLL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_EVENT_CONTROLLER_SCROLL, GtkEventControllerScroll))
#define GTK_EVENT_CONTROLLER_SCROLL_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GTK_TYPE_EVENT_CONTROLLER_SCROLL, GtkEventControllerScrollClass))
#define GTK_IS_EVENT_CONTROLLER_SCROLL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_EVENT_CONTROLLER_SCROLL))
#define GTK_IS_EVENT_CONTROLLER_SCROLL_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_TYPE_EVENT_CONTROLLER_SCROLL))
#define GTK_EVENT_CONTROLLER_SCROLL_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_EVENT_CONTROLLER_SCROLL, GtkEventControllerScrollClass))
typedef struct _GtkEventControllerScroll GtkEventControllerScroll;
typedef struct _GtkEventControllerScrollClass GtkEventControllerScrollClass;
GDK_AVAILABLE_IN_ALL
GDK_DECLARE_EXPORTED_TYPE (GtkEventControllerScroll, gtk_event_controller_scroll, GTK, EVENT_CONTROLLER_SCROLL)
/**
* GtkEventControllerScrollFlags:
@@ -60,9 +54,6 @@ typedef enum {
GTK_EVENT_CONTROLLER_SCROLL_BOTH_AXES = (GTK_EVENT_CONTROLLER_SCROLL_VERTICAL | GTK_EVENT_CONTROLLER_SCROLL_HORIZONTAL),
} GtkEventControllerScrollFlags;
GDK_AVAILABLE_IN_ALL
GType gtk_event_controller_scroll_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_ALL
GtkEventController *gtk_event_controller_scroll_new (GtkEventControllerScrollFlags flags);
GDK_AVAILABLE_IN_ALL
+75 -45
View File
@@ -51,7 +51,7 @@
* Watches can be created for automatically updating the propery of an object,
* similar to GObject's #GBinding mechanism, by using gtk_expression_bind().
*
* #GtkExpression in ui files
* GtkExpression in ui files
*
* GtkBuilder has support for creating expressions. The syntax here can be used where
* a #GtkExpression object is needed like in a <property> tag for an expression
@@ -85,7 +85,7 @@
* |[
* <closure type='gchararray' function='combine_args_somehow'>
* <constant type='gchararray'>File size:</constant>
* <lookup type='gint64' name='size'>myfile</lookup>
* <lookup type='GFile' name='size'>myfile</lookup>
* </closure>
* ]|
*/
@@ -694,7 +694,6 @@ gtk_property_expression_new (GType this_type,
GtkExpression *expression,
const char *property_name)
{
GtkPropertyExpression *result;
GParamSpec *pspec;
if (g_type_is_a (this_type, G_TYPE_OBJECT))
@@ -721,6 +720,15 @@ gtk_property_expression_new (GType this_type,
return NULL;
}
return gtk_property_expression_new_for_pspec (expression, pspec);
}
GtkExpression *
gtk_property_expression_new_for_pspec (GtkExpression *expression,
GParamSpec *pspec)
{
GtkPropertyExpression *result;
result = gtk_expression_alloc (&GTK_PROPERTY_EXPRESSION_CLASS, pspec->value_type);
result->pspec = pspec;
@@ -793,7 +801,10 @@ gtk_closure_expression_evaluate (GtkExpression *expr,
goto out;
}
}
g_value_init_from_instance (instance_and_params, this);
if (this)
g_value_init_from_instance (instance_and_params, this);
else
g_value_init (instance_and_params, G_TYPE_OBJECT);
g_value_init (value, expr->value_type);
g_closure_invoke (self->closure,
@@ -911,7 +922,7 @@ static const GtkExpressionClass GTK_CLOSURE_EXPRESSION_CLASS =
/**
* gtk_closure_expression_new:
* @type: the type of the value that this expression evaluates to
* @value_type: the type of the value that this expression evaluates to
* @closure: closure to call when evaluating this expression. If closure is floating, it is adopted
* @n_params: the number of params needed for evaluating @closure
* @params: (array length=n_params) (transfer full): expressions for each parameter
@@ -951,7 +962,7 @@ gtk_closure_expression_new (GType value_type,
/**
* gtk_cclosure_expression_new:
* @type: the type of the value that this expression evaluates to
* @value_type: the type of the value that this expression evaluates to
* @marshal: 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
@@ -1040,7 +1051,7 @@ gtk_expression_get_value_type (GtkExpression *self)
/**
* gtk_expression_evaluate:
* @self: a #GtkExpression
* @this_: (transfer none) (type GObject): the this argument for the evaluation
* @this_: (transfer none) (type GObject) (nullable): the this argument for the evaluation
* @value: an empty #GValue
*
* Evaluates the given expression and on success stores the result
@@ -1060,6 +1071,7 @@ gtk_expression_evaluate (GtkExpression *self,
GValue *value)
{
g_return_val_if_fail (GTK_IS_EXPRESSION (self), FALSE);
g_return_val_if_fail (this_ == NULL || G_IS_OBJECT (this_), FALSE);
g_return_val_if_fail (value != NULL, FALSE);
return self->expression_class->evaluate (self, this_, value);
@@ -1171,16 +1183,16 @@ gtk_expression_watch (GtkExpression *self,
/**
* gtk_expression_watch_ref:
* @self: (allow-none): a #GtkExpressionWatch
* @watch: (allow-none): a #GtkExpressionWatch
*
* Acquires a reference on the given #GtkExpressionWatch.
*
* Returns: (transfer none): the #GtkExpression with an additional reference
*/
GtkExpressionWatch *
gtk_expression_watch_ref (GtkExpressionWatch *self)
gtk_expression_watch_ref (GtkExpressionWatch *watch)
{
return g_atomic_rc_box_acquire (self);
return g_atomic_rc_box_acquire (watch);
}
static void
@@ -1193,7 +1205,7 @@ gtk_expression_watch_finalize (gpointer data)
/**
* gtk_expression_watch_unref:
* @self: (allow-none): a #GtkExpressionWatch
* @watch: (allow-none): a #GtkExpressionWatch
*
* Releases a reference on the given #GtkExpressionWatch.
*
@@ -1201,9 +1213,9 @@ gtk_expression_watch_finalize (gpointer data)
* freed.
*/
void
gtk_expression_watch_unref (GtkExpressionWatch *self)
gtk_expression_watch_unref (GtkExpressionWatch *watch)
{
g_atomic_rc_box_release_full (self, gtk_expression_watch_finalize);
g_atomic_rc_box_release_full (watch, gtk_expression_watch_finalize);
}
/**
@@ -1258,8 +1270,7 @@ gtk_expression_watch_evaluate (GtkExpressionWatch *watch,
typedef struct {
GtkExpressionWatch *watch;
GtkExpression *expression;
GObject *object;
GObject *target;
GParamSpec *pspec;
} GtkExpressionBind;
@@ -1274,7 +1285,12 @@ invalidate_binds (gpointer unused,
{
GtkExpressionBind *bind = l->data;
bind->object = NULL;
/* This guarantees we neither try to update bindings
* (which would wreck havoc because the object is
* dispose()ing itself) nor try to destroy bindings
* anymore, so destruction can be done in free_binds().
*/
bind->target = NULL;
}
}
@@ -1287,8 +1303,10 @@ free_binds (gpointer data)
{
GtkExpressionBind *bind = l->data;
bind->object = NULL;
gtk_expression_watch_unwatch (bind->watch);
g_assert (bind->target == NULL);
if (bind->watch)
gtk_expression_watch_unwatch (bind->watch);
g_slice_free (GtkExpressionBind, bind);
}
g_slist_free (data);
}
@@ -1298,19 +1316,30 @@ gtk_expression_bind_free (gpointer data)
{
GtkExpressionBind *bind = data;
if (bind->object)
if (bind->target)
{
GSList *binds;
binds = g_object_steal_data (bind->object, "gtk-expression-binds");
binds = g_object_steal_data (bind->target, "gtk-expression-binds");
binds = g_slist_remove (binds, bind);
if (binds)
g_object_set_data_full (bind->object, "gtk-expression-binds", binds, free_binds);
g_object_set_data_full (bind->target, "gtk-expression-binds", binds, free_binds);
else
g_object_weak_unref (bind->object, invalidate_binds, NULL);
}
gtk_expression_unref (bind->expression);
g_object_weak_unref (bind->target, invalidate_binds, NULL);
g_slice_free (GtkExpressionBind, bind);
g_slice_free (GtkExpressionBind, bind);
}
else
{
/* If a bind gets unwatched after invalidate_binds() but
* before free_binds(), we end up here. This can happen if
* the bind was watching itself or if the target's dispose()
* function freed the object that was watched.
* We make sure we don't destroy the binding or free_binds() will do
* bad stuff, but we clear the watch, so free_binds() won't try to
* unwatch() it.
*/
bind->watch = NULL;
}
}
static void
@@ -1319,31 +1348,31 @@ gtk_expression_bind_notify (gpointer data)
GValue value = G_VALUE_INIT;
GtkExpressionBind *bind = data;
if (bind->object == NULL)
if (bind->target == NULL)
return;
if (!gtk_expression_evaluate (bind->expression, bind->object, &value))
if (!gtk_expression_watch_evaluate (bind->watch, &value))
return;
g_object_set_property (bind->object, bind->pspec->name, &value);
g_object_set_property (bind->target, bind->pspec->name, &value);
g_value_unset (&value);
}
/**
* gtk_expression_bind:
* @self: (transfer full): a #GtkExpression
* @object: (transfer none) (type GObject): the object to bind
* @target: (transfer none) (type GObject): the target object to bind to
* @property: name of the property on @target to bind to
* @this_: (transfer none) (type GObject): the this argument for
* the evaluation of @self
* @property: name of the property to bind to
*
* Bind @object's property named @property to @self.
* Bind @target's property named @property to @self.
*
* The value that @self evaluates to is set via g_object_set() on
* @object. This is repeated whenever @self changes to ensure that
* @target. This is repeated whenever @self changes to ensure that
* the object's property stays synchronized with @self.
*
* If @self's evaluation fails, @object's @property is not updated.
* If @self's evaluation fails, @target's @property is not updated.
* You can ensure that this doesn't happen by using a fallback
* expression.
*
@@ -1354,37 +1383,36 @@ gtk_expression_bind_notify (gpointer data)
**/
GtkExpressionWatch *
gtk_expression_bind (GtkExpression *self,
gpointer object,
gpointer this_,
const char *property)
gpointer target,
const char *property,
gpointer this_)
{
GtkExpressionBind *bind;
GParamSpec *pspec;
GSList *binds;
g_return_val_if_fail (GTK_IS_EXPRESSION (self), NULL);
g_return_val_if_fail (G_IS_OBJECT (object), NULL);
g_return_val_if_fail (G_IS_OBJECT (target), NULL);
g_return_val_if_fail (property != NULL, NULL);
pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), property);
pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (target), property);
if (G_UNLIKELY (pspec == NULL))
{
g_critical ("%s: Class '%s' has no property named '%s'",
G_STRFUNC, G_OBJECT_TYPE_NAME (object), property);
G_STRFUNC, G_OBJECT_TYPE_NAME (target), property);
return NULL;
}
if (G_UNLIKELY ((pspec->flags & (G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)) != G_PARAM_WRITABLE))
{
g_critical ("%s: property '%s' of class '%s' is not writable",
G_STRFUNC, pspec->name, G_OBJECT_TYPE_NAME (object));
G_STRFUNC, pspec->name, G_OBJECT_TYPE_NAME (target));
return NULL;
}
bind = g_slice_new0 (GtkExpressionBind);
binds = g_object_steal_data (object, "gtk-expression-binds");
binds = g_object_steal_data (target, "gtk-expression-binds");
if (binds == NULL)
g_object_weak_ref (object, invalidate_binds, NULL);
bind->expression = self;
bind->object = object;
g_object_weak_ref (target, invalidate_binds, NULL);
bind->target = target;
bind->pspec = pspec;
bind->watch = gtk_expression_watch (self,
this_,
@@ -1392,7 +1420,9 @@ gtk_expression_bind (GtkExpression *self,
bind,
gtk_expression_bind_free);
binds = g_slist_prepend (binds, bind);
g_object_set_data_full (object, "gtk-expression-binds", binds, free_binds);
g_object_set_data_full (target, "gtk-expression-binds", binds, free_binds);
gtk_expression_unref (self);
gtk_expression_bind_notify (bind);
+13 -3
View File
@@ -28,6 +28,13 @@ G_BEGIN_DECLS
typedef struct _GtkExpression GtkExpression;
typedef struct _GtkExpressionWatch GtkExpressionWatch;
/**
* GtkExpressionNotify:
* @user_data: data passed to gtk_expression_watch()
*
* Callback called by gtk_expression_watch() when the
* expression value changes.
*/
typedef void (* GtkExpressionNotify) (gpointer user_data);
#define GTK_IS_EXPRESSION(expr) ((expr) != NULL)
@@ -58,9 +65,9 @@ GtkExpressionWatch * gtk_expression_watch (GtkExpression
GDestroyNotify user_destroy);
GDK_AVAILABLE_IN_ALL
GtkExpressionWatch * gtk_expression_bind (GtkExpression *self,
gpointer object,
gpointer this_,
const char * property);
gpointer target,
const char * property,
gpointer this_);
GDK_AVAILABLE_IN_ALL
GtkExpressionWatch * gtk_expression_watch_ref (GtkExpressionWatch *watch);
@@ -77,6 +84,9 @@ GtkExpression * gtk_property_expression_new (GType
GtkExpression *expression,
const char *property_name);
GDK_AVAILABLE_IN_ALL
GtkExpression * gtk_property_expression_new_for_pspec (GtkExpression *expression,
GParamSpec *pspec);
GDK_AVAILABLE_IN_ALL
GtkExpression * gtk_constant_expression_new (GType value_type,
...);
GDK_AVAILABLE_IN_ALL
+81 -64
View File
@@ -29,7 +29,7 @@
#include "gtkcellrendererpixbuf.h"
#include "gtkcellrenderertext.h"
#include "gtkcheckmenuitem.h"
#include "gtkcomboboxtext.h"
#include "gtkdropdown.h"
#include "gtkcssnumbervalueprivate.h"
#include "gtkdragsource.h"
#include "gtkdragdest.h"
@@ -330,7 +330,7 @@ struct _GtkFileChooserWidgetPrivate {
GSList *pending_select_files;
GtkFileFilter *current_filter;
GSList *filters;
GListStore *filters;
GtkBookmarksManager *bookmarks_manager;
@@ -565,7 +565,8 @@ static void set_current_filter (GtkFileChooserWidget *impl,
GtkFileFilter *filter);
static void check_preview_change (GtkFileChooserWidget *impl);
static void filter_combo_changed (GtkComboBox *combo_box,
static void filter_combo_changed (GtkDropDown *dropdown,
GParamSpec *pspec,
GtkFileChooserWidget *impl);
static gboolean list_select_func (GtkTreeSelection *selection,
@@ -702,7 +703,7 @@ gtk_file_chooser_widget_finalize (GObject *object)
g_free (priv->browse_files_last_selected_name);
g_slist_free_full (priv->filters, g_object_unref);
g_clear_object (&priv->filters);
g_clear_object (&priv->current_filter);
g_clear_object (&priv->current_folder);
g_clear_object (&priv->browse_path_bar_size_group);
@@ -6093,24 +6094,18 @@ gtk_file_chooser_widget_add_filter (GtkFileChooser *chooser,
{
GtkFileChooserWidget *impl = GTK_FILE_CHOOSER_WIDGET (chooser);
GtkFileChooserWidgetPrivate *priv = gtk_file_chooser_widget_get_instance_private (impl);
const gchar *name;
if (g_slist_find (priv->filters, filter))
if (g_list_store_find (priv->filters, filter, NULL))
{
g_warning ("gtk_file_chooser_add_filter() called on filter already in list");
return;
}
g_object_ref_sink (filter);
priv->filters = g_slist_append (priv->filters, filter);
g_list_store_append (priv->filters, filter);
g_object_unref (filter);
name = gtk_file_filter_get_name (filter);
if (!name)
name = "Untitled filter"; /* Place-holder, doesn't need to be marked for translation */
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (priv->filter_combo), name);
if (!g_slist_find (priv->filters, priv->current_filter))
if (!priv->current_filter)
set_current_filter (impl, filter);
show_filters (impl, TRUE);
@@ -6122,35 +6117,28 @@ gtk_file_chooser_widget_remove_filter (GtkFileChooser *chooser,
{
GtkFileChooserWidget *impl = GTK_FILE_CHOOSER_WIDGET (chooser);
GtkFileChooserWidgetPrivate *priv = gtk_file_chooser_widget_get_instance_private (impl);
GtkTreeModel *model;
GtkTreeIter iter;
gint filter_index;
guint filter_index;
filter_index = g_slist_index (priv->filters, filter);
if (filter_index < 0)
if (!g_list_store_find (priv->filters, filter, &filter_index))
{
g_warning ("gtk_file_chooser_remove_filter() called on filter not in list");
return;
}
priv->filters = g_slist_remove (priv->filters, filter);
g_list_store_remove (priv->filters, filter_index);
if (filter == priv->current_filter)
{
if (priv->filters)
set_current_filter (impl, priv->filters->data);
{
GtkFileFilter *f = g_list_model_get_item (G_LIST_MODEL (priv->filters), 0);
set_current_filter (impl, f);
g_object_unref (f);
}
else
set_current_filter (impl, NULL);
}
/* Remove row from the combo box */
model = gtk_combo_box_get_model (GTK_COMBO_BOX (priv->filter_combo));
if (!gtk_tree_model_iter_nth_child (model, &iter, NULL, filter_index))
g_assert_not_reached ();
gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
g_object_unref (filter);
if (!priv->filters)
@@ -6162,8 +6150,19 @@ gtk_file_chooser_widget_list_filters (GtkFileChooser *chooser)
{
GtkFileChooserWidget *impl = GTK_FILE_CHOOSER_WIDGET (chooser);
GtkFileChooserWidgetPrivate *priv = gtk_file_chooser_widget_get_instance_private (impl);
GSList *filters;
guint i;
return g_slist_copy (priv->filters);
filters = NULL;
for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (priv->filters)); i++)
{
GtkFileFilter *filter = g_list_model_get_item (G_LIST_MODEL (priv->filters), i);
filters = g_slist_append (filters, filter);
g_object_unref (filter);
}
return filters;
}
static gboolean
@@ -7542,7 +7541,7 @@ recent_start_loading (GtkFileChooserWidget *impl)
g_list_free_full (folders, g_object_unref);
}
g_list_free_full (items, (GDestroyNotify) gtk_recent_info_unref);
g_list_free_full (items, (GDestroyNotify) g_object_unref);
gtk_tree_view_set_model (GTK_TREE_VIEW (priv->browse_files_tree_view),
GTK_TREE_MODEL (priv->recent_model));
@@ -7580,11 +7579,11 @@ set_current_filter (GtkFileChooserWidget *impl,
if (priv->current_filter != filter)
{
int filter_index;
guint filter_index;
g_print ("set current filter\n");
/* NULL filters are allowed to reset to non-filtered status */
filter_index = g_slist_index (priv->filters, filter);
if (priv->filters && filter && filter_index < 0)
if (filter && !g_list_store_find (priv->filters, filter, &filter_index))
return;
if (priv->current_filter)
@@ -7593,9 +7592,9 @@ set_current_filter (GtkFileChooserWidget *impl,
if (priv->current_filter)
g_object_ref_sink (priv->current_filter);
if (priv->filters)
gtk_combo_box_set_active (GTK_COMBO_BOX (priv->filter_combo), filter_index);
gtk_drop_down_set_selected (GTK_DROP_DOWN (priv->filter_combo), filter_index);
g_print ("set current filter %u\n", filter_index);
clear_model_cache (impl, MODEL_COL_IS_SENSITIVE);
set_model_filter (impl, priv->current_filter);
g_object_notify (G_OBJECT (impl), "filter");
@@ -7603,20 +7602,22 @@ set_current_filter (GtkFileChooserWidget *impl,
}
static void
filter_combo_changed (GtkComboBox *combo_box,
filter_combo_changed (GtkDropDown *dropdown,
GParamSpec *pspec,
GtkFileChooserWidget *impl)
{
GtkFileChooserWidgetPrivate *priv = gtk_file_chooser_widget_get_instance_private (impl);
gint new_index;
GtkFileFilter *new_filter;
new_index = gtk_combo_box_get_active (combo_box);
new_filter = g_slist_nth_data (priv->filters, new_index);
new_index = gtk_drop_down_get_selected (dropdown);
new_filter = g_list_model_get_item (G_LIST_MODEL (priv->filters), new_index);
set_current_filter (impl, new_filter);
if (priv->location_entry != NULL)
_gtk_file_chooser_entry_set_file_filter (GTK_FILE_CHOOSER_ENTRY (priv->location_entry),
new_filter);
g_object_unref (new_filter);
}
static void
@@ -8509,8 +8510,6 @@ post_process_ui (GtkFileChooserWidget *impl)
{
GtkFileChooserWidgetPrivate *priv = gtk_file_chooser_widget_get_instance_private (impl);
GtkTreeSelection *selection;
GtkCellRenderer *cell;
GList *cells;
GFile *file;
/* Setup file list treeview */
@@ -8537,20 +8536,6 @@ post_process_ui (GtkFileChooserWidget *impl)
file_list_set_sort_column_ids (impl);
update_cell_renderer_attributes (impl);
/* Get the combo's text renderer and set ellipsize parameters,
* perhaps GtkComboBoxText should declare the cell renderer
* as an 'internal-child', then we could configure it in GtkBuilder
* instead of hard coding it here.
*/
cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (priv->filter_combo));
g_assert (cells);
cell = cells->data;
g_object_set (G_OBJECT (cell),
"ellipsize", PANGO_ELLIPSIZE_END,
NULL);
g_list_free (cells);
/* Set the GtkPathBar file system backend */
_gtk_path_bar_set_file_system (GTK_PATH_BAR (priv->browse_path_bar), priv->file_system);
file = g_file_new_for_path ("/");
@@ -8599,10 +8584,17 @@ display_changed_cb (GtkWidget *wiget,
check_icon_theme (impl);
}
static char *
filter_name (GtkFileFilter *filter)
{
return g_strdup (gtk_file_filter_get_name (filter));
}
static void
gtk_file_chooser_widget_init (GtkFileChooserWidget *impl)
{
GtkFileChooserWidgetPrivate *priv = gtk_file_chooser_widget_get_instance_private (impl);
GtkExpression *expression;
profile_start ("start", NULL);
#ifdef PROFILE_FILE_CHOOSER
@@ -8645,6 +8637,16 @@ gtk_file_chooser_widget_init (GtkFileChooserWidget *impl)
priv->file_system = _gtk_file_system_new ();
priv->bookmarks_manager = _gtk_bookmarks_manager_new (NULL, NULL);
priv->filters = g_list_store_new (GTK_TYPE_FILE_FILTER);
gtk_drop_down_set_model (GTK_DROP_DOWN (priv->filter_combo), G_LIST_MODEL (priv->filters));
expression = gtk_cclosure_expression_new (G_TYPE_STRING, NULL,
0, NULL,
G_CALLBACK (filter_name),
NULL, NULL);
gtk_drop_down_set_expression (GTK_DROP_DOWN (priv->filter_combo), expression);
gtk_expression_unref (expression);
/* Setup various attributes and callbacks in the UI
* which cannot be done with GtkBuilder
*/
@@ -8698,18 +8700,16 @@ gtk_file_chooser_widget_add_choice (GtkFileChooser *chooser,
{
GtkWidget *box;
GtkWidget *combo;
int i;
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
gtk_container_add (GTK_CONTAINER (box), gtk_label_new (label));
combo = gtk_combo_box_text_new ();
combo = gtk_drop_down_new ();
g_hash_table_insert (priv->choices, g_strdup (id), combo);
gtk_container_add (GTK_CONTAINER (box), combo);
for (i = 0; options[i]; i++)
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo),
options[i], option_labels[i]);
gtk_drop_down_set_from_strings (GTK_DROP_DOWN (combo), option_labels);
g_object_set_data_full (G_OBJECT (combo), "options", g_strdupv ((char **)options), (GDestroyNotify)g_strfreev);
widget = box;
}
@@ -8764,8 +8764,19 @@ gtk_file_chooser_widget_set_choice (GtkFileChooser *chooser,
widget = (GtkWidget *)g_hash_table_lookup (priv->choices, id);
if (GTK_IS_COMBO_BOX (widget))
gtk_combo_box_set_active_id (GTK_COMBO_BOX (widget), option);
if (GTK_IS_DROP_DOWN (widget))
{
guint i;
const char **options = (const char **)g_object_get_data (G_OBJECT (widget), "options");
for (i = 0; options[i]; i++)
{
if (strcmp (options[i], option) == 0)
{
gtk_drop_down_set_selected (GTK_DROP_DOWN (widget), i);
break;
}
}
}
else if (GTK_IS_TOGGLE_BUTTON (widget))
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), g_str_equal (option, "true"));
}
@@ -8782,8 +8793,14 @@ gtk_file_chooser_widget_get_choice (GtkFileChooser *chooser,
return NULL;
widget = (GtkWidget *)g_hash_table_lookup (priv->choices, id);
if (GTK_IS_COMBO_BOX (widget))
return gtk_combo_box_get_active_id (GTK_COMBO_BOX (widget));
if (GTK_IS_DROP_DOWN (widget))
{
const char **options = (const char **)g_object_get_data (G_OBJECT (widget), "options");
guint selected = gtk_drop_down_get_selected (GTK_DROP_DOWN (widget));
if (selected == GTK_INVALID_LIST_POSITION)
return NULL;
return options[selected];
}
else if (GTK_IS_TOGGLE_BUTTON (widget))
return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)) ? "true" : "false";
+1 -1
View File
@@ -27,7 +27,7 @@
/**
* SECTION:gtkfilter
* @Title: GtkFilter
* @Short_description: Filtering items in GTK
* @Short_description: Filtering items
* @See_also: #GtkFilerListModel
*
* #GtkFilter is the way to describe filters to be used in #GtkFilterListModel.
+3 -11
View File
@@ -53,18 +53,12 @@ typedef enum {
* GtkFilterChange:
* @GTK_FILTER_CHANGE_DIFFERENT: The filter change cannot be
* described with any of the other enumeration values.
* @GTK_FILTER_CHANGE_MATCH_ALL: The filter now matches every
* item: gtk_filter_get_strictness() will now return
* %GTK_FILTER_MATCH_ALL
* @GTK_FILTER_CHANGE_LESS_STRICT: The filter is less strict than
* it was before: All items that it used to return %TRUE for
* still return %TRUE, others now may, too.
* @GTK_FILTER_CHANGE_MORE_STRICT: The filter is more strict than
* it was before: All items that it used to return %FALSE for
* still return %FALSE, others now may, too.
* @GTK_FILTER_CHANGE_MATCH_NONE: The filter now matches no item:
* gtk_filter_get_strictness() will now return
* %GTK_FILTER_MATCH_NONE
*
* Describes changes in a filter in more detail and allows objects
* using the filter to optimize refiltering items.
@@ -75,10 +69,8 @@ typedef enum {
*/
typedef enum {
GTK_FILTER_CHANGE_DIFFERENT = 0,
GTK_FILTER_CHANGE_MATCH_ALL,
GTK_FILTER_CHANGE_LESS_STRICT,
GTK_FILTER_CHANGE_MORE_STRICT,
GTK_FILTER_CHANGE_MATCH_NONE
} GtkFilterChange;
#define GTK_TYPE_FILTER (gtk_filter_get_type ())
@@ -113,14 +105,14 @@ struct _GtkFilterClass
};
GDK_AVAILABLE_IN_ALL
gboolean gtk_filter_match (GtkFilter *filter,
gboolean gtk_filter_match (GtkFilter *self,
gpointer item);
GDK_AVAILABLE_IN_ALL
GtkFilterMatch gtk_filter_get_strictness (GtkFilter *filter);
GtkFilterMatch gtk_filter_get_strictness (GtkFilter *self);
/* for filter implementations */
GDK_AVAILABLE_IN_ALL
void gtk_filter_changed (GtkFilter *filter,
void gtk_filter_changed (GtkFilter *self,
GtkFilterChange change);
+3 -3
View File
@@ -29,12 +29,12 @@
* SECTION:gtkfilterlistmodel
* @title: GtkFilterListModel
* @short_description: A list model that filters its items
* @see_also: #GListModel
* @see_also: #GListModel, #GtkFilter
*
* #GtkFilterListModel is a list model that filters a given other
* listmodel.
* It hides some elements from the other model according to
* criteria given by a #GtkFilterListModelFilterFunc.
* criteria given by a #GtkFilter.
*/
enum {
@@ -726,7 +726,7 @@ gtk_filter_list_model_new (GListModel *model,
* @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 function and model to ensure
* It is up to the application to set a proper filter and model to ensure
* the item type is matched.
*
* Returns: a new #GtkFilterListModel
-14
View File
@@ -27,7 +27,6 @@
#include <gio/gio.h>
#include <gtk/gtkfilter.h>
#include <gtk/gtkwidget.h>
G_BEGIN_DECLS
@@ -37,19 +36,6 @@ G_BEGIN_DECLS
GDK_AVAILABLE_IN_ALL
G_DECLARE_FINAL_TYPE (GtkFilterListModel, gtk_filter_list_model, GTK, FILTER_LIST_MODEL, GObject)
/**
* GtkFilterListModelFilterFunc:
* @item: (type GObject): The item that may be filtered
* @user_data: user data
*
* User function that is called to determine if the @item of the original model should be visible.
* If it should be visible, this function must return %TRUE. If the model should filter out the
* @item, %FALSE must be returned.
*
* Returns: %TRUE to keep the item around
*/
typedef gboolean (* GtkFilterListModelFilterFunc) (gpointer item, gpointer user_data);
GDK_AVAILABLE_IN_ALL
GtkFilterListModel * gtk_filter_list_model_new (GListModel *model,
GtkFilter *filter);
-270
View File
@@ -1,270 +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 "gtkfilters.h"
#include "gtkintl.h"
#include "gtktypebuiltins.h"
/*** CUSTOM FILTER ***/
struct _GtkCustomFilter
{
GtkFilter parent_instance;
GtkCustomFilterFunc match_func;
gpointer user_data;
GDestroyNotify user_destroy;
};
G_DEFINE_TYPE (GtkCustomFilter, gtk_custom_filter, GTK_TYPE_FILTER)
static gboolean
gtk_custom_filter_match (GtkFilter *filter,
gpointer item)
{
GtkCustomFilter *self = GTK_CUSTOM_FILTER (filter);
return self->match_func (item, self->user_data);
}
static void
gtk_custom_filter_dispose (GObject *object)
{
GtkCustomFilter *self = GTK_CUSTOM_FILTER (object);
if (self->user_destroy)
self->user_destroy (self->user_data);
G_OBJECT_CLASS (gtk_custom_filter_parent_class)->dispose (object);
}
static void
gtk_custom_filter_class_init (GtkCustomFilterClass *class)
{
GtkFilterClass *filter_class = GTK_FILTER_CLASS (class);
GObjectClass *object_class = G_OBJECT_CLASS (class);
filter_class->match = gtk_custom_filter_match;
object_class->dispose = gtk_custom_filter_dispose;
}
static void
gtk_custom_filter_init (GtkCustomFilter *self)
{
}
/**
* gtk_custom_filter_new:
* @match_func: Function to filter items
* @user_data: (allow none): user data to pass to @match_func
* @user_destroy: destory notify
*
* Creates a new filter using the given @match_func to filter
* items.
*
* If the filter func changes its filtering behavior,
* gtk_filter_changed() needs to be called.
*
* Returns: a new #GtkFilter
**/
GtkFilter *
gtk_custom_filter_new (GtkCustomFilterFunc match_func,
gpointer user_data,
GDestroyNotify user_destroy)
{
GtkCustomFilter *result;
result = g_object_new (GTK_TYPE_CUSTOM_FILTER, NULL);
result->match_func = match_func;
result->user_data = user_data;
result->user_destroy = user_destroy;
return GTK_FILTER (result);
}
/*** ANY FILTER ***/
struct _GtkAnyFilter
{
GtkFilter parent_instance;
GSequence *filters;
};
static GType
gtk_any_filter_get_item_type (GListModel *list)
{
return GTK_TYPE_FILTER;
}
static guint
gtk_any_filter_get_n_items (GListModel *list)
{
GtkAnyFilter *self = GTK_ANY_FILTER (list);
return g_sequence_get_length (self->filters);
}
static gpointer
gtk_any_filter_get_item (GListModel *list,
guint position)
{
GtkAnyFilter *self = GTK_ANY_FILTER (list);
GSequenceIter *iter;
iter = g_sequence_get_iter_at_pos (self->filters, position);
if (g_sequence_iter_is_end (iter))
return NULL;
else
return g_object_ref (g_sequence_get (iter));
}
static void
gtk_any_filter_list_model_init (GListModelInterface *iface)
{
iface->get_item_type = gtk_any_filter_get_item_type;
iface->get_n_items = gtk_any_filter_get_n_items;
iface->get_item = gtk_any_filter_get_item;
}
G_DEFINE_TYPE_WITH_CODE (GtkAnyFilter, gtk_any_filter, GTK_TYPE_FILTER,
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, gtk_any_filter_list_model_init))
static gboolean
gtk_any_filter_match (GtkFilter *filter,
gpointer item)
{
GtkAnyFilter *self = GTK_ANY_FILTER (filter);
GSequenceIter *iter;
for (iter = g_sequence_get_begin_iter (self->filters);
!g_sequence_iter_is_end (iter);
iter = g_sequence_iter_next (iter))
{
GtkFilter *child = g_sequence_get (iter);
if (gtk_filter_match (child, item))
return TRUE;
}
return FALSE;
}
static void
gtk_any_filter_dispose (GObject *object)
{
GtkAnyFilter *self = GTK_ANY_FILTER (object);
g_clear_pointer (&self->filters, g_sequence_free);
G_OBJECT_CLASS (gtk_any_filter_parent_class)->dispose (object);
}
static void
gtk_any_filter_class_init (GtkAnyFilterClass *class)
{
GtkFilterClass *filter_class = GTK_FILTER_CLASS (class);
GObjectClass *object_class = G_OBJECT_CLASS (class);
filter_class->match = gtk_any_filter_match;
object_class->dispose = gtk_any_filter_dispose;
}
static void
gtk_any_filter_init (GtkAnyFilter *self)
{
self->filters = g_sequence_new (g_object_unref);
gtk_filter_changed (GTK_FILTER (self), GTK_FILTER_CHANGE_MATCH_NONE);
}
/**
* gtk_any_filter_new:
*
* Creates a new "any" filter.
*
* This filter matches an item if any of the filters added to it
* matches the item.
* In particular, this means that if no filter has been added to
* it, the filter matches no item.
*
* Returns: a new #GtkFilter
**/
GtkFilter *
gtk_any_filter_new (void)
{
return g_object_new (GTK_TYPE_ANY_FILTER, NULL);
}
/**
* gtk_any_filter_append:
* @self: a #GtkAnyFilter
* @filter: (tranfer none): A new filter to use
*
* Adds a @filter to @self to use for matching.
**/
void
gtk_any_filter_append (GtkAnyFilter *self,
GtkFilter *filter)
{
g_return_if_fail (GTK_IS_ANY_FILTER (self));
g_return_if_fail (GTK_IS_FILTER (filter));
g_sequence_append (self->filters, g_object_ref (filter));
gtk_filter_changed (GTK_FILTER (self), GTK_FILTER_CHANGE_LESS_STRICT);
}
/**
* gtk_any_filter_remove:
* @self: a #GtkAnyFilter
* @position: position of filter to remove
*
* Removes the filter at the given @position from the list of filters used
* by @self.
* If @position is larger than the number of filters, nothing happens and
* the function returns.
**/
void
gtk_any_filter_remove (GtkAnyFilter *self,
guint position)
{
GSequenceIter *iter;
guint length;
g_return_if_fail (GTK_IS_ANY_FILTER (self));
length = g_sequence_get_length (self->filters);
if (position >= length)
return;
iter = g_sequence_get_iter_at_pos (self->filters, position);
g_sequence_remove (iter);
gtk_filter_changed (GTK_FILTER (self), length == 1
? GTK_FILTER_CHANGE_MATCH_NONE
: GTK_FILTER_CHANGE_MORE_STRICT);
}
+39 -72
View File
@@ -30,7 +30,7 @@
#include "gtkbuildable.h"
#include "gtkbox.h"
#include "gtkbinlayout.h"
#include "gtkcssnumbervalueprivate.h"
#include "gtkcustomfilter.h"
#include "gtkentry.h"
#include "gtkfilter.h"
#include "gtkgrid.h"
@@ -113,9 +113,8 @@ struct _GtkFontChooserWidgetPrivate
GtkWidget *family_face_list;
GtkWidget *list_stack;
GtkSingleSelection *selection;
GtkFilter *custom_filter;
GtkCustomFilter *custom_filter;
GtkFilterListModel *filter_model;
GListModel *fontlist;
GtkWidget *preview;
GtkWidget *preview2;
@@ -859,71 +858,6 @@ gtk_font_chooser_widget_new (void)
return g_object_new (GTK_TYPE_FONT_CHOOSER_WIDGET, NULL);
}
#if 0
static gboolean
visible_func (GtkTreeModel *model,
GtkTreeIter *iter,
gpointer user_data)
{
GtkFontChooserWidgetPrivate *priv = user_data;
gboolean result = TRUE;
const gchar *search_text;
gchar **split_terms;
gchar *font_name, *font_name_casefold;
guint i;
if (priv->filter_func != NULL)
{
PangoFontFamily *family;
PangoFontFace *face;
gtk_tree_model_get (model, iter,
FAMILY_COLUMN, &family,
FACE_COLUMN, &face,
-1);
result = priv->filter_func (family, face, priv->filter_data);
g_object_unref (family);
g_object_unref (face);
if (!result)
return FALSE;
}
/* If there's no filter string we show the item */
search_text = gtk_editable_get_text (GTK_EDITABLE (priv->search_entry));
if (strlen (search_text) == 0)
return TRUE;
gtk_tree_model_get (model, iter,
PREVIEW_TITLE_COLUMN, &font_name,
-1);
if (font_name == NULL)
return FALSE;
split_terms = g_strsplit (search_text, " ", 0);
font_name_casefold = g_utf8_casefold (font_name, -1);
for (i = 0; split_terms[i] && result; i++)
{
gchar* term_casefold = g_utf8_casefold (split_terms[i], -1);
if (!strstr (font_name_casefold, term_casefold))
result = FALSE;
g_free (term_casefold);
}
g_free (font_name_casefold);
g_free (font_name);
g_strfreev (split_terms);
return result;
}
#endif
static void
gtk_font_chooser_widget_finalize (GObject *object)
{
@@ -2057,14 +1991,37 @@ gtk_font_chooser_widget_get_font_map (GtkFontChooser *chooser)
return priv->font_map;
}
static gboolean
gtk_font_chooser_widget_filter_cb (gpointer item,
gpointer data)
{
GtkFontChooserWidget *fontchooser = GTK_FONT_CHOOSER_WIDGET (data);
GtkFontChooserWidgetPrivate *priv = gtk_font_chooser_widget_get_instance_private (fontchooser);
PangoFontFamily *family;
PangoFontFace *face;
if (PANGO_IS_FONT_FAMILY (item))
{
family = item;
face = pango_font_family_get_face (family, NULL);
}
else
{
face = item;
family = pango_font_face_get_family (face);
}
return priv->filter_func (family, face, priv->filter_data);
}
static void
gtk_font_chooser_widget_set_filter_func (GtkFontChooser *chooser,
gtk_font_chooser_widget_set_filter_func (GtkFontChooser *chooser,
GtkFontFilterFunc filter,
gpointer data,
GDestroyNotify destroy)
{
GtkFontChooserWidget *fontchooser = GTK_FONT_CHOOSER_WIDGET (chooser);
GtkFontChooserWidgetPrivate *priv = gtk_font_chooser_widget_get_instance_private (fontchooser);
GtkFontChooserWidget *self = GTK_FONT_CHOOSER_WIDGET (chooser);
GtkFontChooserWidgetPrivate *priv = gtk_font_chooser_widget_get_instance_private (self);
if (priv->filter_data_destroy)
priv->filter_data_destroy (priv->filter_data);
@@ -2073,7 +2030,17 @@ gtk_font_chooser_widget_set_filter_func (GtkFontChooser *chooser,
priv->filter_data = data;
priv->filter_data_destroy = destroy;
gtk_filter_changed (priv->custom_filter, GTK_FILTER_CHANGE_DIFFERENT);
if (filter)
{
gtk_custom_filter_set_filter_func (priv->custom_filter,
gtk_font_chooser_widget_filter_cb,
self,
NULL);
}
else
{
gtk_custom_filter_set_filter_func (priv->custom_filter, NULL, NULL, NULL);
}
}
static void

Some files were not shown because too many files have changed in this diff Show More