gboolean keyboard_mode,
GtkTooltip *tooltip);
-static gboolean gtk_calendar_drag_motion (GtkDropTarget *dest,
+static gboolean gtk_calendar_drag_accept (GtkDropTarget *dest,
GdkDrop *drop,
- int x,
- int y,
GtkCalendar *calendar);
static void gtk_calendar_drag_leave (GtkDropTarget *dest,
GdkDrop *drop,
dest = gtk_drop_target_new (formats, GDK_ACTION_COPY);
gdk_content_formats_unref (formats);
- g_signal_connect (dest, "accept", G_CALLBACK (gtk_calendar_drag_motion), calendar);
+ g_signal_connect (dest, "accept", G_CALLBACK (gtk_calendar_drag_accept), calendar);
g_signal_connect (dest, "drag-leave", G_CALLBACK (gtk_calendar_drag_leave), calendar);
g_signal_connect (dest, "drag-drop", G_CALLBACK (gtk_calendar_drag_drop), calendar);
GAsyncResult *result,
gpointer data)
{
- GtkCalendar *calendar = GTK_CALENDAR (data);
+ GtkDropTarget *dest = GTK_DROP_TARGET (data);
+ GtkCalendar *calendar = GTK_CALENDAR (gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (dest)));
GtkCalendarPrivate *priv = gtk_calendar_get_instance_private (calendar);
GdkDrop *drop = GDK_DROP (source);
guint day, month, year;
}
else
suggested_action = 0;
-
gdk_drop_status (drop, suggested_action);
+ if (suggested_action == 0)
+ gtk_drop_target_deny_drop (dest, drop);
return;
}
g_warning ("Received invalid date data");
g_date_free (date);
gdk_drop_finish (drop, 0);
+ gtk_drop_target_deny_drop (dest, drop);
return;
}
}
static gboolean
-gtk_calendar_drag_motion (GtkDropTarget *dest,
+gtk_calendar_drag_accept (GtkDropTarget *dest,
GdkDrop *drop,
- int x,
- int y,
GtkCalendar *calendar)
{
GdkAtom target;
target = gtk_drop_target_find_mimetype (dest);
if (!target || gdk_drop_get_actions (drop) == 0)
- gdk_drop_status (drop, 0);
+ {
+ gdk_drop_status (drop, 0);
+ return FALSE;
+ }
else if (get_status_pending (drop) == 0)
{
set_status_pending (drop, gdk_drop_get_actions (drop));
- gdk_drop_read_text_async (drop, NULL, got_text, calendar);
+ gdk_drop_read_text_async (drop, NULL, got_text, dest);
}
-
return TRUE;
}
if (target != NULL)
{
set_status_pending (drop, 0);
- gdk_drop_read_text_async (drop, NULL, got_text, calendar);
+ gdk_drop_read_text_async (drop, NULL, got_text, dest);
return TRUE;
}
int baseline);
static gboolean gtk_expander_focus (GtkWidget *widget,
GtkDirectionType direction);
-static gboolean gtk_expander_drag_motion (GtkDropTarget *dest,
+static gboolean gtk_expander_drag_accept (GtkDropTarget *dest,
GdkDrop *drop,
- int x,
- int y,
GtkExpander *expander);
static void gtk_expander_drag_leave (GtkDropTarget *dest,
GdkDrop *drop,
formats = gdk_content_formats_new (NULL, 0);
dest = gtk_drop_target_new (formats, 0);
gdk_content_formats_unref (formats);
- g_signal_connect (dest, "accept", G_CALLBACK (gtk_expander_drag_motion), expander);
+ g_signal_connect (dest, "accept", G_CALLBACK (gtk_expander_drag_accept), expander);
g_signal_connect (dest, "drag-leave", G_CALLBACK (gtk_expander_drag_leave), expander);
gtk_widget_add_controller (GTK_WIDGET (expander), GTK_EVENT_CONTROLLER (dest));
}
static gboolean
-gtk_expander_drag_motion (GtkDropTarget *dest,
+gtk_expander_drag_accept (GtkDropTarget *dest,
GdkDrop *drop,
- int x,
- int y,
GtkExpander *expander)
{
GtkExpanderPrivate *priv = gtk_expander_get_instance_private (expander);
/* Disable the normal tree drag motion handler, it makes it look like you're
dropping the dragged item onto a tree item */
static gboolean
-file_list_drag_motion_cb (GtkDropTarget *dest,
+file_list_drag_accept_cb (GtkDropTarget *dest,
GdkDrop *drop,
- int x,
- int y,
GtkFileChooserWidget *impl)
{
g_signal_stop_emission_by_name (dest, "accept");
GDK_ACTION_COPY | GDK_ACTION_MOVE);
dest = gtk_drop_target_new (formats, GDK_ACTION_COPY | GDK_ACTION_MOVE);
- g_signal_connect (dest, "accept", G_CALLBACK (file_list_drag_motion_cb), impl);
+ g_signal_connect (dest, "accept", G_CALLBACK (file_list_drag_accept_cb), impl);
g_signal_connect (dest, "drag-drop", G_CALLBACK (file_list_drag_drop_cb), impl);
gtk_widget_add_controller (priv->browse_files_tree_view, GTK_EVENT_CONTROLLER (dest));
gdk_content_formats_unref (formats);
static void gtk_icon_view_drag_leave (GtkDropTarget *dest,
GdkDrop *drop,
GtkIconView *icon_view);
-static gboolean gtk_icon_view_drag_motion (GtkDropTarget *dest,
+static void gtk_icon_view_drag_motion (GtkDropTarget *dest,
GdkDrop *drop,
int x,
int y,
remove_scroll_timeout (icon_view);
}
-static gboolean
+static void
gtk_icon_view_drag_motion (GtkDropTarget *dest,
GdkDrop *drop,
int x,
gboolean empty;
if (!set_destination (icon_view, dest, x, y, &suggested_action, &target))
- return FALSE;
-
- icon_view->priv->event_last_x = x;
- icon_view->priv->event_last_y = y;
+ {
+ gdk_drop_status (drop, 0);
+ return;
+ }
gtk_icon_view_get_drag_dest_item (icon_view, &path, &pos);
if (path)
gtk_tree_path_free (path);
-
- return TRUE;
}
static gboolean
icon_view->priv->dest = gtk_drop_target_new (formats, actions);
g_signal_connect (icon_view->priv->dest, "drag-leave", G_CALLBACK (gtk_icon_view_drag_leave), icon_view);
- g_signal_connect (icon_view->priv->dest, "accept", G_CALLBACK (gtk_icon_view_drag_motion), icon_view);
+ g_signal_connect (icon_view->priv->dest, "drag-motion", G_CALLBACK (gtk_icon_view_drag_motion), icon_view);
g_signal_connect (icon_view->priv->dest, "drag-drop", G_CALLBACK (gtk_icon_view_drag_drop), icon_view);
gtk_widget_add_controller (GTK_WIDGET (icon_view), GTK_EVENT_CONTROLLER (icon_view->priv->dest));
static void gtk_notebook_drag_cancel_cb (GdkDrag *drag,
GdkDragCancelReason reason,
GtkWidget *widget);
-static gboolean gtk_notebook_drag_motion (GtkDropTarget *dest,
+static void gtk_notebook_drag_motion (GtkDropTarget *dest,
GdkDrop *drop,
int x,
int y);
targets = gdk_content_formats_new (dst_notebook_targets, G_N_ELEMENTS (dst_notebook_targets));
dest = gtk_drop_target_new (targets, GDK_ACTION_MOVE);
- g_signal_connect (dest, "accept", G_CALLBACK (gtk_notebook_drag_motion), NULL);
+ g_signal_connect (dest, "drag-motion", G_CALLBACK (gtk_notebook_drag_motion), NULL);
g_signal_connect (dest, "drag-leave", G_CALLBACK (gtk_notebook_drag_leave), NULL);
g_signal_connect (dest, "drag-drop", G_CALLBACK (gtk_notebook_drag_drop), NULL);
gtk_widget_add_controller (GTK_WIDGET (priv->tabs_widget), GTK_EVENT_CONTROLLER (dest));
return FALSE;
}
-static gboolean
+static void
gtk_notebook_drag_motion (GtkDropTarget *dest,
GdkDrop *drop,
int x,
GtkNotebookArrow arrow;
GdkAtom target, tab_target;
GList *tab;
- gboolean retval = FALSE;
arrow = gtk_notebook_get_arrow (notebook, x, y);
if (arrow != ARROW_NONE)
gtk_notebook_set_scroll_timer (notebook);
gdk_drop_status (drop, 0);
- retval = TRUE;
goto out;
}
GtkWidget *source_child;
GdkDrag *drag = gdk_drop_get_drag (drop);
- retval = TRUE;
-
if (!drag)
{
gdk_drop_status (drop, 0);
priv->mouse_x = x;
priv->mouse_y = y;
- retval = TRUE;
-
if (tab != priv->switch_tab)
remove_switch_tab_timer (notebook);
remove_switch_tab_timer (notebook);
}
- out:
- return retval;
+ out:;
}
static void
return g_object_new (GTK_TYPE_SIDEBAR_ROW, "placeholder", TRUE, NULL);
}
-static gboolean
+static void
drag_motion_callback (GtkDropTarget *dest,
GdkDrop *drop,
- gint x,
- gint y,
- gpointer user_data)
+ gint x,
+ gint y,
+ gpointer user_data)
{
GtkPlacesSidebar *sidebar = GTK_PLACES_SIDEBAR (user_data);
gint action;
out:
start_drop_feedback (sidebar, GTK_SIDEBAR_ROW (row), drag);
-
gdk_drop_status (drop, action);
-
- return TRUE;
}
/* Takes an array of URIs and turns it into a list of GFile */
formats = gdk_content_formats_builder_free_to_formats (builder);
dest = gtk_drop_target_new (formats, GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK);
gdk_content_formats_unref (formats);
- g_signal_connect (dest, "accept", G_CALLBACK (drag_motion_callback), sidebar);
+ g_signal_connect (dest, "drag-motion", G_CALLBACK (drag_motion_callback), sidebar);
g_signal_connect (dest, "drag-drop", G_CALLBACK (drag_drop_callback), sidebar);
g_signal_connect (dest, "drag-leave", G_CALLBACK (drag_leave_callback), sidebar);
gtk_widget_add_controller (sidebar->list_box, GTK_EVENT_CONTROLLER (dest));
--- /dev/null
+/*
+ * Copyright © 2019 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Matthias Clasen <mclasen@redhat.com>
+ */
+
+#include "config.h"
+
+#include "gtksearchlistmodel.h"
+
+#include "gtkintl.h"
+#include "gtkselectionmodel.h"
+
+/**
+ * SECTION:gtksearchlistmodel
+ * @Short_description: A selection model that allows incremental searching
+ * @Title: GtkSearchListModel
+ * @see_also: #GtkSelectionModel
+ *
+ * GtkSearchListModel is an implementation of the #GtkSelectionModel interface
+ * that allows selecting a single element. The selected element can be determined
+ * interactively via a filter.
+ */
+struct _GtkSearchListModel
+{
+ GObject parent_instance;
+
+ GListModel *model;
+ guint selected;
+ gpointer selected_item;
+
+ GtkFilter *filter;
+};
+
+struct _GtkSearchListModelClass
+{
+ GObjectClass parent_class;
+};
+
+enum {
+ PROP_0,
+ PROP_MODEL,
+ PROP_FILTER,
+ PROP_SELECTED,
+ PROP_SELECTED_ITEM,
+
+ N_PROPS
+};
+
+static GParamSpec *properties[N_PROPS] = { NULL, };
+
+static GType
+gtk_search_list_model_get_item_type (GListModel *list)
+{
+ GtkSearchListModel *self = GTK_SEARCH_LIST_MODEL (list);
+
+ return g_list_model_get_item_type (self->model);
+}
+
+static guint
+gtk_search_list_model_get_n_items (GListModel *list)
+{
+ GtkSearchListModel *self = GTK_SEARCH_LIST_MODEL (list);
+
+ return g_list_model_get_n_items (self->model);
+}
+
+static gpointer
+gtk_search_list_model_get_item (GListModel *list,
+ guint position)
+{
+ GtkSearchListModel *self = GTK_SEARCH_LIST_MODEL (list);
+
+ return g_list_model_get_item (self->model, position);
+}
+
+static void
+gtk_search_list_model_list_model_init (GListModelInterface *iface)
+{
+ iface->get_item_type = gtk_search_list_model_get_item_type;
+ iface->get_n_items = gtk_search_list_model_get_n_items;
+ iface->get_item = gtk_search_list_model_get_item;
+}
+
+static gboolean
+gtk_search_list_model_is_selected (GtkSelectionModel *model,
+ guint position)
+{
+ GtkSearchListModel *self = GTK_SEARCH_LIST_MODEL (model);
+
+ return self->selected == position;
+}
+
+static void
+gtk_search_list_model_query_range (GtkSelectionModel *model,
+ guint position,
+ guint *start_range,
+ guint *n_range,
+ gboolean *selected)
+{
+ GtkSearchListModel *self = GTK_SEARCH_LIST_MODEL (model);
+ guint n_items;
+
+ n_items = g_list_model_get_n_items (self->model);
+
+ if (position >= n_items)
+ {
+ *start_range = position;
+ *n_range = 0;
+ *selected = FALSE;
+ }
+ else if (self->selected == GTK_INVALID_LIST_POSITION)
+ {
+ *start_range = 0;
+ *n_range = n_items;
+ *selected = FALSE;
+ }
+ else if (position < self->selected)
+ {
+ *start_range = 0;
+ *n_range = self->selected;
+ *selected = FALSE;
+ }
+ else if (position > self->selected)
+ {
+ *start_range = self->selected + 1;
+ *n_range = n_items - *start_range;
+ *selected = FALSE;
+ }
+ else
+ {
+ *start_range = self->selected;
+ *n_range = 1;
+ *selected = TRUE;
+ }
+}
+
+static void
+gtk_search_list_model_selection_model_init (GtkSelectionModelInterface *iface)
+{
+ iface->is_selected = gtk_search_list_model_is_selected;
+ iface->query_range = gtk_search_list_model_query_range;
+}
+
+G_DEFINE_TYPE_EXTENDED (GtkSearchListModel, gtk_search_list_model, G_TYPE_OBJECT, 0,
+ G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL,
+ gtk_search_list_model_list_model_init)
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_SELECTION_MODEL,
+ gtk_search_list_model_selection_model_init))
+
+static void
+gtk_search_list_model_items_changed_cb (GListModel *model,
+ guint position,
+ guint removed,
+ guint added,
+ GtkSearchListModel *self)
+{
+ g_object_freeze_notify (G_OBJECT (self));
+
+ if (self->selected_item == NULL)
+ {
+ /* nothing to do */
+ }
+ else if (self->selected < position)
+ {
+ /* unchanged */
+ }
+ else if (self->selected >= position + removed)
+ {
+ self->selected += added - removed;
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SELECTED]);
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SELECTED_ITEM]);
+ }
+ else
+ {
+ guint i;
+
+ for (i = 0; i < added; i++)
+ {
+ gpointer item = g_list_model_get_item (model, position + i);
+ if (item == self->selected_item)
+ {
+ /* the item moved */
+ //TODO refilter
+ if (self->selected != position + i)
+ {
+ self->selected = position + i;
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SELECTED]);
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SELECTED_ITEM]);
+ }
+ break;
+ }
+ }
+ if (i == added)
+ {
+ /* the item really was deleted */
+ g_clear_object (&self->selected_item);
+ self->selected = GTK_INVALID_LIST_POSITION;
+ //TODO refilter
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SELECTED]);
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SELECTED_ITEM]);
+ }
+ }
+
+ g_list_model_items_changed (G_LIST_MODEL (self), position, removed, added);
+
+ g_object_thaw_notify (G_OBJECT (self));
+}
+
+static void
+set_selected (GtkSearchListModel *self,
+ guint position)
+{
+ gpointer new_selected = NULL;
+ guint old_position;
+
+ if (self->selected == position)
+ return;
+
+ new_selected = g_list_model_get_item (self->model, position);
+
+ if (new_selected == NULL)
+ position = GTK_INVALID_LIST_POSITION;
+
+ if (self->selected == position)
+ return;
+
+ old_position = self->selected;
+ self->selected = position;
+ g_clear_object (&self->selected_item);
+ self->selected_item = new_selected;
+
+ if (old_position == GTK_INVALID_LIST_POSITION)
+ gtk_selection_model_selection_changed (GTK_SELECTION_MODEL (self), position, 1);
+ else if (position == GTK_INVALID_LIST_POSITION)
+ gtk_selection_model_selection_changed (GTK_SELECTION_MODEL (self), old_position, 1);
+ else if (position < old_position)
+ gtk_selection_model_selection_changed (GTK_SELECTION_MODEL (self), position, old_position - position + 1);
+ else
+ gtk_selection_model_selection_changed (GTK_SELECTION_MODEL (self), old_position, position - old_position + 1);
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SELECTED]);
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SELECTED_ITEM]);
+}
+
+static gboolean
+match_item (GtkSearchListModel *self,
+ guint position)
+{
+ gpointer item;
+ gboolean result;
+
+ item = g_list_model_get_item (self->model, position);
+ result = gtk_filter_match (self->filter, item);
+ g_object_unref (item);
+
+ return result;
+}
+
+static guint
+find_next_match (GtkSearchListModel *self,
+ guint position,
+ gboolean forward)
+{
+ guint i;
+
+ if (position == GTK_INVALID_LIST_POSITION)
+ position = 0;
+
+ g_print ("search %s from %u\n", forward ? "forward" : "backward", position);
+ if (forward)
+ for (i = position; i < g_list_model_get_n_items (self->model); i++)
+ {
+ if (match_item (self, i))
+ return i;
+ }
+ else
+ for (i = position; ; i--)
+ {
+ if (match_item (self, i))
+ return i;
+ if (i == 0)
+ break;
+ }
+
+ return GTK_INVALID_LIST_POSITION;
+}
+
+static void
+gtk_search_list_model_filter_changed_cb (GtkFilter *filter,
+ GtkFilterChange change,
+ GtkSearchListModel *self)
+{
+ guint position;
+
+g_print ("filter changed: change %d, strictness %d\n", change, gtk_filter_get_strictness (self->filter));
+
+ if (gtk_filter_get_strictness (self->filter) == GTK_FILTER_MATCH_NONE)
+ position = GTK_INVALID_LIST_POSITION;
+ else
+ switch (change)
+ {
+ case GTK_FILTER_CHANGE_DIFFERENT:
+ case GTK_FILTER_CHANGE_LESS_STRICT:
+ position = find_next_match (self, 0, TRUE);
+ break;
+ case GTK_FILTER_CHANGE_MORE_STRICT:
+ position = find_next_match (self, self->selected, TRUE);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ g_print ("select %u\n", position);
+ set_selected (self, position);
+}
+
+static void
+gtk_search_list_model_clear_model (GtkSearchListModel *self)
+{
+ if (self->model == NULL)
+ return;
+
+ g_signal_handlers_disconnect_by_func (self->model,
+ gtk_search_list_model_items_changed_cb,
+ self);
+ g_clear_object (&self->model);
+}
+
+static void
+gtk_search_list_model_clear_filter (GtkSearchListModel *self)
+{
+ if (self->filter == NULL)
+ return;
+
+ g_signal_handlers_disconnect_by_func (self->filter,
+ gtk_search_list_model_filter_changed_cb,
+ self);
+
+ g_clear_object (&self->filter);
+}
+
+static void
+gtk_search_list_model_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+
+{
+ GtkSearchListModel *self = GTK_SEARCH_LIST_MODEL (object);
+
+ switch (prop_id)
+ {
+ case PROP_MODEL:
+ self->model = g_value_dup_object (value);
+ g_signal_connect (self->model, "items-changed",
+ G_CALLBACK (gtk_search_list_model_items_changed_cb), self);
+ break;
+
+ case PROP_FILTER:
+ self->filter = g_value_dup_object (value);
+ g_signal_connect (self->filter, "changed",
+ G_CALLBACK (gtk_search_list_model_filter_changed_cb), self);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_search_list_model_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtkSearchListModel *self = GTK_SEARCH_LIST_MODEL (object);
+
+ switch (prop_id)
+ {
+ case PROP_MODEL:
+ g_value_set_object (value, self->model);
+ break;
+
+ case PROP_FILTER:
+ g_value_set_object (value, self->filter);
+ break;
+
+ case PROP_SELECTED:
+ g_value_set_uint (value, self->selected);
+ break;
+
+ case PROP_SELECTED_ITEM:
+ g_value_set_object (value, self->selected_item);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_search_list_model_dispose (GObject *object)
+{
+ GtkSearchListModel *self = GTK_SEARCH_LIST_MODEL (object);
+
+ gtk_search_list_model_clear_model (self);
+ gtk_search_list_model_clear_filter (self);
+
+ self->selected = GTK_INVALID_LIST_POSITION;
+ g_clear_object (&self->selected_item);
+
+ G_OBJECT_CLASS (gtk_search_list_model_parent_class)->dispose (object);
+}
+
+static void
+gtk_search_list_model_class_init (GtkSearchListModelClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->get_property = gtk_search_list_model_get_property;
+ gobject_class->set_property = gtk_search_list_model_set_property;
+ gobject_class->dispose = gtk_search_list_model_dispose;
+
+ /**
+ * GtkSearchListModel:selected:
+ *
+ * Position of the selected item
+ */
+ properties[PROP_SELECTED] =
+ g_param_spec_uint ("selected",
+ P_("Selected"),
+ P_("Position of the selected item"),
+ 0, G_MAXUINT, GTK_INVALID_LIST_POSITION,
+ G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
+
+ /**
+ * GtkSearchListModel:selected-item:
+ *
+ * The selected item
+ */
+ properties[PROP_SELECTED_ITEM] =
+ g_param_spec_object ("selected-item",
+ P_("Selected Item"),
+ P_("The selected item"),
+ G_TYPE_OBJECT,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+ /**
+ * GtkSearchListModel:model:
+ *
+ * The model being managed
+ */
+ properties[PROP_MODEL] =
+ g_param_spec_object ("model",
+ P_("The model"),
+ P_("The model being managed"),
+ G_TYPE_LIST_MODEL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+ /**
+ * GtkSearchListModel:filter:
+ *
+ * The filter determining the selected item
+ */
+ properties[PROP_FILTER] =
+ g_param_spec_object ("filter",
+ P_("The filter"),
+ P_("The filter being used"),
+ GTK_TYPE_FILTER,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (gobject_class, N_PROPS, properties);
+}
+
+static void
+gtk_search_list_model_init (GtkSearchListModel *self)
+{
+ self->selected = GTK_INVALID_LIST_POSITION;
+}
+
+/**
+ * gtk_search_list_model_new:
+ * @model: (transfer none): the #GListModel to manage
+ * @filter: (transfer none): the #GtkFilter to use
+ *
+ * Creates a new selection to handle @model.
+ *
+ * Returns: (transfer full) (type GtkSearchListModel): a new #GtkSearchListModel
+ **/
+GtkSearchListModel *
+gtk_search_list_model_new (GListModel *model,
+ GtkFilter *filter)
+{
+ g_return_val_if_fail (G_IS_LIST_MODEL (model), NULL);
+
+ return g_object_new (GTK_TYPE_SEARCH_LIST_MODEL,
+ "model", model,
+ "filter", filter,
+ NULL);
+}
+
+gboolean
+gtk_search_list_model_next_match (GtkSearchListModel *self)
+{
+ guint position;
+
+ position = find_next_match (self, self->selected, TRUE);
+ if (position == GTK_INVALID_LIST_POSITION)
+ return FALSE;
+
+ set_selected (self, position);
+
+ return TRUE;
+}
+
+gboolean
+gtk_search_list_model_previous_match (GtkSearchListModel *self)
+{
+ guint position;
+
+ position = find_next_match (self, self->selected, FALSE);
+ if (position == GTK_INVALID_LIST_POSITION)
+ return FALSE;
+
+ set_selected (self, position);
+
+ return TRUE;
+}
--- /dev/null
+/*
+ * Copyright © 2019 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Matthias Clasen <mclasen@redhat.com>
+ */
+
+#ifndef __GTK_SEARCH_LIST_MODEL_H__
+#define __GTK_SEARCH_LIST_MODEL_H__
+
+
+#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gtk/gtk.h> can be included directly."
+#endif
+
+#include <gio/gio.h>
+#include <gtk/gtkfilter.h>
+
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_SEARCH_LIST_MODEL (gtk_search_list_model_get_type ())
+
+GDK_AVAILABLE_IN_ALL
+G_DECLARE_FINAL_TYPE (GtkSearchListModel, gtk_search_list_model, GTK, SEARCH_LIST_MODEL, GObject)
+
+GDK_AVAILABLE_IN_ALL
+GtkSearchListModel * gtk_search_list_model_new (GListModel *model,
+ GtkFilter *filter);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_search_list_model_next_match (GtkSearchListModel *self);
+
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_search_list_model_previous_match (GtkSearchListModel *self);
+
+G_END_DECLS
+
+#endif /* __GTK_SEARCH_LIST_MODEL_H__ */
static void gtk_stack_switcher_drag_leave (GtkDropTarget *dest,
GdkDrop *drop,
GtkStackSwitcher *self);
-static gboolean gtk_stack_switcher_drag_motion (GtkDropTarget *dest,
+static gboolean gtk_stack_switcher_drag_accept (GtkDropTarget *dest,
+ GdkDrop *drop,
+ GtkStackSwitcher *self);
+static void gtk_stack_switcher_drag_motion (GtkDropTarget *dest,
GdkDrop *drop,
int x,
int y,
dest = gtk_drop_target_new (formats, 0);
gdk_content_formats_unref (formats);
g_signal_connect (dest, "drag-leave", G_CALLBACK (gtk_stack_switcher_drag_leave), switcher);
- g_signal_connect (dest, "accept", G_CALLBACK (gtk_stack_switcher_drag_motion), switcher);
+ g_signal_connect (dest, "accept", G_CALLBACK (gtk_stack_switcher_drag_accept), switcher);
+ g_signal_connect (dest, "drag-motion", G_CALLBACK (gtk_stack_switcher_drag_motion), switcher);
gtk_widget_add_controller (GTK_WIDGET (switcher), GTK_EVENT_CONTROLLER (dest));
}
}
static gboolean
+gtk_stack_switcher_drag_accept (GtkDropTarget *dest,
+ GdkDrop *drop,
+ GtkStackSwitcher *self)
+{
+ return TRUE;
+}
+
+static void
gtk_stack_switcher_drag_motion (GtkDropTarget *dest,
GdkDrop *drop,
int x,
GtkWidget *button;
GHashTableIter iter;
gpointer value;
- gboolean retval = FALSE;
button = NULL;
g_hash_table_iter_init (&iter, priv->buttons);
if (gtk_widget_contains (GTK_WIDGET (value), cx, cy))
{
button = GTK_WIDGET (value);
- retval = TRUE;
break;
}
}
self);
g_source_set_name_by_id (priv->switch_timer, "[gtk] gtk_stack_switcher_switch_timeout");
}
-
- return retval;
}
static void
int x,
int y,
GtkText *text);
-static gboolean gtk_text_drag_motion (GtkDropTarget *dest,
+static gboolean gtk_text_drag_accept (GtkDropTarget *dest,
+ GdkDrop *drop,
+ GtkText *self);
+static void gtk_text_drag_motion (GtkDropTarget *dest,
GdkDrop *drop,
int x,
int y,
formats = gdk_content_formats_new_for_gtype (G_TYPE_STRING);
dest = gtk_drop_target_new (formats, GDK_ACTION_COPY | GDK_ACTION_MOVE);
- g_signal_connect (dest, "accept", G_CALLBACK (gtk_text_drag_motion), self);
+ g_signal_connect (dest, "accept", G_CALLBACK (gtk_text_drag_accept), self);
+ g_signal_connect (dest, "drag-motion", G_CALLBACK (gtk_text_drag_motion), self);
g_signal_connect (dest, "drag-leave", G_CALLBACK (gtk_text_drag_leave), self);
g_signal_connect (dest, "drag-drop", G_CALLBACK (gtk_text_drag_drop), self);
gdk_content_formats_unref (formats);
}
static gboolean
+gtk_text_drag_accept (GtkDropTarget *dest,
+ GdkDrop *drop,
+ GtkText *self)
+{
+ GtkTextPrivate *priv = gtk_text_get_instance_private (self);
+ GdkDragAction suggested_action;
+
+ if (priv->editable &&
+ gtk_drop_target_find_mimetype (dest) != NULL)
+ {
+ suggested_action = GDK_ACTION_COPY | GDK_ACTION_MOVE;
+ }
+ else
+ {
+ /* Entry not editable, or no text */
+ suggested_action = 0;
+ }
+
+ gdk_drop_status (drop, suggested_action);
+ return suggested_action != 0;
+}
+
+static void
gtk_text_drag_motion (GtkDropTarget *dest,
GdkDrop *drop,
int x,
GtkText *self)
{
GtkTextPrivate *priv = gtk_text_get_instance_private (self);
- GtkWidget *widget = GTK_WIDGET (self);
- GdkDragAction suggested_action;
int new_position, old_position;
old_position = priv->dnd_position;
if (priv->editable &&
gtk_drop_target_find_mimetype (dest) != NULL)
{
- suggested_action = GDK_ACTION_COPY | GDK_ACTION_MOVE;
-
if (priv->selection_bound == priv->current_pos ||
new_position < priv->selection_bound ||
new_position > priv->current_pos)
else
{
/* Entry not editable, or no text */
- suggested_action = 0;
priv->dnd_position = -1;
}
- gdk_drop_status (drop, suggested_action);
-
if (priv->dnd_position != old_position)
- gtk_widget_queue_draw (widget);
-
- return TRUE;
+ gtk_widget_queue_draw (GTK_WIDGET (self));
}
/* We display the cursor when
dest = gtk_drop_target_new (formats, GDK_ACTION_COPY | GDK_ACTION_MOVE);
gdk_content_formats_unref (formats);
g_signal_connect (dest, "drag-leave", G_CALLBACK (gtk_text_view_drag_leave), text_view);
- g_signal_connect (dest, "accept", G_CALLBACK (gtk_text_view_drag_motion), text_view);
+ g_signal_connect (dest, "drag-motion", G_CALLBACK (gtk_text_view_drag_motion), text_view);
g_signal_connect (dest, "drag-drop", G_CALLBACK (gtk_text_view_drag_drop), text_view);
gtk_widget_add_controller (GTK_WIDGET (text_view), GTK_EVENT_CONTROLLER (dest));
static void gtk_tree_view_drag_leave (GtkDropTarget *dest,
GdkDrop *drop,
GtkTreeView *tree_view);
-static gboolean gtk_tree_view_drag_motion (GtkDropTarget *dest,
+static void gtk_tree_view_drag_motion (GtkDropTarget *dest,
GdkDrop *drop,
int x,
int y,
}
-static gboolean
+static void
gtk_tree_view_drag_motion (GtkDropTarget *dest,
GdkDrop *drop,
int x,
GdkAtom target;
if (!set_destination_row (tree_view, dest, x, y, &suggested_action, &target))
- return FALSE;
+ {
+ gdk_drop_status (drop, 0);
+ return;
+ }
tree_view->event_last_x = x;
tree_view->event_last_y = y;
if (path)
gtk_tree_path_free (path);
-
- return TRUE;
}
di->dest = gtk_drop_target_new (formats, actions);
g_signal_connect (di->dest, "drag-leave", G_CALLBACK (gtk_tree_view_drag_leave), tree_view);
- g_signal_connect (di->dest, "accept", G_CALLBACK (gtk_tree_view_drag_motion), tree_view);
+ g_signal_connect (di->dest, "drag-motion", G_CALLBACK (gtk_tree_view_drag_motion), tree_view);
g_signal_connect (di->dest, "drag-drop", G_CALLBACK (gtk_tree_view_drag_drop), tree_view);
gtk_widget_add_controller (GTK_WIDGET (tree_view), GTK_EVENT_CONTROLLER (di->dest));
g_object_ref (di->dest);
gboolean
popup_motion (GtkDropTarget *dest,
- GdkDrop *drop,
- int x,
- int y)
+ GdkDrop *drop)
{
gdk_drop_status (drop, GDK_ACTION_COPY);
return TRUE;
static gboolean
image_drag_motion (GtkDropTarget *dest,
GdkDrop *drop,
- int x,
- int y,
gpointer data)
{
GtkWidget *image = data;
static gboolean
item_drag_motion (GtkDropTarget *dest,
- GdkDrop *drop,
- int x,
- int y)
+ GdkDrop *drop)
{
if (gtk_drop_target_find_mimetype (dest) != NULL)
{