forked from AuroraMiddleware/gtk
New function.
Sat Aug 14 17:56:33 2004 Soeren Sandmann <sandmann@daimi.au.dk> * gtk/gtkentry.c (gtk_entry_get_pixel_ranges): New function. * gtk/gtkentry.c (in_selection): New function using gtk_entry_get_pixel_ranges() to determine whether a click is in the selection. Improve entry behavior wrt. dragging and selecting. Bug #143249. Sat Aug 14 17:53:46 2004 Soeren Sandmann <sandmann@daimi.au.dk> * configure.in: Require glib 2.5.2 * gtk/gtksequence.[ch]: New internal data structure. * gtk/gtkliststore.[hc]: Reimplement in terms of new data structure * tests/Makefile.am (testtreemodel_SOURCES): * tests/testtreemodel.c: New test program written by Matthias.
This commit is contained in:
parent
766d78659c
commit
15ed3634a9
21
ChangeLog
21
ChangeLog
@ -1,3 +1,24 @@
|
||||
Sat Aug 14 17:56:33 2004 Soeren Sandmann <sandmann@daimi.au.dk>
|
||||
|
||||
* gtk/gtkentry.c (gtk_entry_get_pixel_ranges): New function.
|
||||
|
||||
* gtk/gtkentry.c (in_selection): New function using
|
||||
gtk_entry_get_pixel_ranges() to determine whether a click is in
|
||||
the selection. Improve entry behavior wrt. dragging and
|
||||
selecting. Bug #143249.
|
||||
|
||||
Sat Aug 14 17:53:46 2004 Soeren Sandmann <sandmann@daimi.au.dk>
|
||||
|
||||
* configure.in: Require glib 2.5.2
|
||||
|
||||
* gtk/gtksequence.[ch]: New internal data structure.
|
||||
|
||||
* gtk/gtkliststore.[hc]: Reimplement in terms of new data
|
||||
structure
|
||||
|
||||
* tests/Makefile.am (testtreemodel_SOURCES):
|
||||
* tests/testtreemodel.c: New test program written by Matthias.
|
||||
|
||||
2004-08-13 Matthias Clasen <mclasen@redhat.com>
|
||||
|
||||
* gtk/gtkfilechooserdefault.c (gtk_file_chooser_default_style_set):
|
||||
|
@ -1,3 +1,24 @@
|
||||
Sat Aug 14 17:56:33 2004 Soeren Sandmann <sandmann@daimi.au.dk>
|
||||
|
||||
* gtk/gtkentry.c (gtk_entry_get_pixel_ranges): New function.
|
||||
|
||||
* gtk/gtkentry.c (in_selection): New function using
|
||||
gtk_entry_get_pixel_ranges() to determine whether a click is in
|
||||
the selection. Improve entry behavior wrt. dragging and
|
||||
selecting. Bug #143249.
|
||||
|
||||
Sat Aug 14 17:53:46 2004 Soeren Sandmann <sandmann@daimi.au.dk>
|
||||
|
||||
* configure.in: Require glib 2.5.2
|
||||
|
||||
* gtk/gtksequence.[ch]: New internal data structure.
|
||||
|
||||
* gtk/gtkliststore.[hc]: Reimplement in terms of new data
|
||||
structure
|
||||
|
||||
* tests/Makefile.am (testtreemodel_SOURCES):
|
||||
* tests/testtreemodel.c: New test program written by Matthias.
|
||||
|
||||
2004-08-13 Matthias Clasen <mclasen@redhat.com>
|
||||
|
||||
* gtk/gtkfilechooserdefault.c (gtk_file_chooser_default_style_set):
|
||||
|
@ -1,3 +1,24 @@
|
||||
Sat Aug 14 17:56:33 2004 Soeren Sandmann <sandmann@daimi.au.dk>
|
||||
|
||||
* gtk/gtkentry.c (gtk_entry_get_pixel_ranges): New function.
|
||||
|
||||
* gtk/gtkentry.c (in_selection): New function using
|
||||
gtk_entry_get_pixel_ranges() to determine whether a click is in
|
||||
the selection. Improve entry behavior wrt. dragging and
|
||||
selecting. Bug #143249.
|
||||
|
||||
Sat Aug 14 17:53:46 2004 Soeren Sandmann <sandmann@daimi.au.dk>
|
||||
|
||||
* configure.in: Require glib 2.5.2
|
||||
|
||||
* gtk/gtksequence.[ch]: New internal data structure.
|
||||
|
||||
* gtk/gtkliststore.[hc]: Reimplement in terms of new data
|
||||
structure
|
||||
|
||||
* tests/Makefile.am (testtreemodel_SOURCES):
|
||||
* tests/testtreemodel.c: New test program written by Matthias.
|
||||
|
||||
2004-08-13 Matthias Clasen <mclasen@redhat.com>
|
||||
|
||||
* gtk/gtkfilechooserdefault.c (gtk_file_chooser_default_style_set):
|
||||
|
@ -1,3 +1,24 @@
|
||||
Sat Aug 14 17:56:33 2004 Soeren Sandmann <sandmann@daimi.au.dk>
|
||||
|
||||
* gtk/gtkentry.c (gtk_entry_get_pixel_ranges): New function.
|
||||
|
||||
* gtk/gtkentry.c (in_selection): New function using
|
||||
gtk_entry_get_pixel_ranges() to determine whether a click is in
|
||||
the selection. Improve entry behavior wrt. dragging and
|
||||
selecting. Bug #143249.
|
||||
|
||||
Sat Aug 14 17:53:46 2004 Soeren Sandmann <sandmann@daimi.au.dk>
|
||||
|
||||
* configure.in: Require glib 2.5.2
|
||||
|
||||
* gtk/gtksequence.[ch]: New internal data structure.
|
||||
|
||||
* gtk/gtkliststore.[hc]: Reimplement in terms of new data
|
||||
structure
|
||||
|
||||
* tests/Makefile.am (testtreemodel_SOURCES):
|
||||
* tests/testtreemodel.c: New test program written by Matthias.
|
||||
|
||||
2004-08-13 Matthias Clasen <mclasen@redhat.com>
|
||||
|
||||
* gtk/gtkfilechooserdefault.c (gtk_file_chooser_default_style_set):
|
||||
|
@ -29,7 +29,7 @@ m4_define([gtk_api_version], [2.0])
|
||||
m4_define([gtk_binary_version], [2.4.0])
|
||||
|
||||
# required versions of other packages
|
||||
m4_define([glib_required_version], [2.4.0])
|
||||
m4_define([glib_required_version], [2.5.2])
|
||||
m4_define([pango_required_version], [1.5.1])
|
||||
m4_define([atk_required_version], [1.0.1])
|
||||
|
||||
|
@ -285,7 +285,7 @@ gtk_semi_private_h_sources = \
|
||||
gtkfilesystem.h
|
||||
|
||||
# GTK+ header files that don't get installed
|
||||
gtk_private_h_sources = \
|
||||
gtk_private_h_sources = \
|
||||
gtkentryprivate.h \
|
||||
gtkfilechooserembed.h \
|
||||
gtkfilechooserentry.h \
|
||||
@ -296,9 +296,10 @@ gtk_private_h_sources = \
|
||||
gtkfilesystemmodel.h \
|
||||
gtkinternals.h \
|
||||
gtkpathbar.h \
|
||||
gtkrbtree.h \
|
||||
gtkrbtree.h \
|
||||
gtksequence.h \
|
||||
gtktextbtree.h \
|
||||
gtktextchildprivate.h \
|
||||
gtktextchildprivate.h \
|
||||
gtktextsegment.h \
|
||||
gtktexttypes.h \
|
||||
gtktextutil.h \
|
||||
@ -441,6 +442,7 @@ gtk_c_sources = \
|
||||
gtkscale.c \
|
||||
gtkscrollbar.c \
|
||||
gtkscrolledwindow.c \
|
||||
gtksequence.c \
|
||||
gtkselection.c \
|
||||
gtkseparator.c \
|
||||
gtkseparatormenuitem.c \
|
||||
|
@ -1400,6 +1400,70 @@ gtk_entry_expose (GtkWidget *widget,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_entry_get_pixel_ranges (GtkEntry *entry,
|
||||
gint **ranges,
|
||||
gint *n_ranges)
|
||||
{
|
||||
gint start_char, end_char;
|
||||
|
||||
if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &start_char, &end_char))
|
||||
{
|
||||
PangoLayout *layout = gtk_entry_ensure_layout (entry, TRUE);
|
||||
PangoLayoutLine *line = pango_layout_get_lines (layout)->data;
|
||||
const char *text = pango_layout_get_text (layout);
|
||||
gint start_index = g_utf8_offset_to_pointer (text, start_char) - text;
|
||||
gint end_index = g_utf8_offset_to_pointer (text, end_char) - text;
|
||||
gint real_n_ranges, i;
|
||||
|
||||
pango_layout_line_get_x_ranges (line, start_index, end_index, ranges, &real_n_ranges);
|
||||
|
||||
if (ranges)
|
||||
{
|
||||
gint *r = *ranges;
|
||||
|
||||
for (i = 0; i < real_n_ranges; ++i)
|
||||
{
|
||||
r[2 * i + 1] = (r[2 * i + 1] - r[2 * i]) / PANGO_SCALE;
|
||||
r[2 * i] = r[2 * i] / PANGO_SCALE;
|
||||
}
|
||||
}
|
||||
|
||||
if (n_ranges)
|
||||
*n_ranges = real_n_ranges;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (n_ranges)
|
||||
*n_ranges = 0;
|
||||
if (ranges)
|
||||
*ranges = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
in_selection (GtkEntry *entry,
|
||||
gint x)
|
||||
{
|
||||
gint *ranges;
|
||||
gint n_ranges, i;
|
||||
gint retval = FALSE;
|
||||
|
||||
gtk_entry_get_pixel_ranges (entry, &ranges, &n_ranges);
|
||||
|
||||
for (i = 0; i < n_ranges; ++i)
|
||||
{
|
||||
if (x >= ranges[2 * i] && x < ranges[2 * i] + ranges[2 * i + 1])
|
||||
{
|
||||
retval = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_free (ranges);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static gint
|
||||
gtk_entry_button_press (GtkWidget *widget,
|
||||
GdkEventButton *event)
|
||||
@ -1491,21 +1555,18 @@ gtk_entry_button_press (GtkWidget *widget,
|
||||
switch (event->type)
|
||||
{
|
||||
case GDK_BUTTON_PRESS:
|
||||
if (have_selection && tmp_pos >= sel_start && tmp_pos <= sel_end)
|
||||
if (in_selection (entry, event->x + entry->scroll_offset))
|
||||
{
|
||||
/* Click inside the selection - we'll either start a drag, or
|
||||
* clear the selection
|
||||
*/
|
||||
|
||||
entry->in_drag = TRUE;
|
||||
entry->drag_start_x = event->x + entry->scroll_offset;
|
||||
entry->drag_start_y = event->y + entry->scroll_offset;
|
||||
}
|
||||
else
|
||||
gtk_editable_set_position (editable, tmp_pos);
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case GDK_2BUTTON_PRESS:
|
||||
/* We ALWAYS receive a GDK_BUTTON_PRESS immediately before
|
||||
@ -2997,7 +3058,6 @@ static void
|
||||
gtk_entry_draw_text (GtkEntry *entry)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
PangoLayoutLine *line;
|
||||
|
||||
if (!entry->visible && entry->invisible_char == 0)
|
||||
return;
|
||||
@ -3021,19 +3081,12 @@ gtk_entry_draw_text (GtkEntry *entry)
|
||||
gint *ranges;
|
||||
gint n_ranges, i;
|
||||
PangoRectangle logical_rect;
|
||||
const gchar *text = pango_layout_get_text (layout);
|
||||
gint start_index = g_utf8_offset_to_pointer (text, start_pos) - text;
|
||||
gint end_index = g_utf8_offset_to_pointer (text, end_pos) - text;
|
||||
GdkRegion *clip_region = gdk_region_new ();
|
||||
GdkGC *text_gc;
|
||||
GdkGC *selection_gc;
|
||||
GdkGC *selection_gc, *text_gc;
|
||||
GdkRegion *clip_region;
|
||||
|
||||
line = pango_layout_get_lines (layout)->data;
|
||||
|
||||
pango_layout_line_get_x_ranges (line, start_index, end_index, &ranges, &n_ranges);
|
||||
pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
|
||||
gtk_entry_get_pixel_ranges (entry, &ranges, &n_ranges);
|
||||
|
||||
pango_layout_get_extents (layout, NULL, &logical_rect);
|
||||
|
||||
if (GTK_WIDGET_HAS_FOCUS (entry))
|
||||
{
|
||||
selection_gc = widget->style->base_gc [GTK_STATE_SELECTED];
|
||||
@ -3045,21 +3098,22 @@ gtk_entry_draw_text (GtkEntry *entry)
|
||||
text_gc = widget->style->text_gc [GTK_STATE_ACTIVE];
|
||||
}
|
||||
|
||||
for (i=0; i < n_ranges; i++)
|
||||
clip_region = gdk_region_new ();
|
||||
for (i = 0; i < n_ranges; ++i)
|
||||
{
|
||||
GdkRectangle rect;
|
||||
|
||||
rect.x = INNER_BORDER - entry->scroll_offset + ranges[2*i] / PANGO_SCALE;
|
||||
rect.x = INNER_BORDER - entry->scroll_offset + ranges[2 * i];
|
||||
rect.y = y;
|
||||
rect.width = (ranges[2*i + 1] - ranges[2*i]) / PANGO_SCALE;
|
||||
rect.height = logical_rect.height / PANGO_SCALE;
|
||||
rect.width = ranges[2 * i + 1];
|
||||
rect.height = logical_rect.height;
|
||||
|
||||
gdk_draw_rectangle (entry->text_area, selection_gc, TRUE,
|
||||
rect.x, rect.y, rect.width, rect.height);
|
||||
|
||||
gdk_region_union_with_rect (clip_region, &rect);
|
||||
}
|
||||
|
||||
|
||||
gdk_gc_set_clip_region (text_gc, clip_region);
|
||||
gdk_draw_layout (entry->text_area, text_gc,
|
||||
x, y,
|
||||
|
1080
gtk/gtkliststore.c
1080
gtk/gtkliststore.c
File diff suppressed because it is too large
Load Diff
@ -43,14 +43,14 @@ struct _GtkListStore
|
||||
|
||||
/*< private >*/
|
||||
gint stamp;
|
||||
gpointer root;
|
||||
gpointer tail;
|
||||
GList *sort_list;
|
||||
gpointer seq; /* head of the list */
|
||||
gpointer _gtk_reserved1;
|
||||
GList *sort_list;
|
||||
gint n_columns;
|
||||
gint sort_column_id;
|
||||
GtkSortType order;
|
||||
GType *column_headers;
|
||||
gint length;
|
||||
gint _gtk_reserved2;
|
||||
GtkTreeIterCompareFunc default_sort_func;
|
||||
gpointer default_sort_data;
|
||||
GtkDestroyNotify default_sort_destroy;
|
||||
|
1104
gtk/gtksequence.c
Normal file
1104
gtk/gtksequence.c
Normal file
File diff suppressed because it is too large
Load Diff
104
gtk/gtksequence.h
Normal file
104
gtk/gtksequence.h
Normal file
@ -0,0 +1,104 @@
|
||||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 2002 Soeren Sandmann (sandmann@daimi.au.dk)
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#ifndef __GSEQUENCE_H__
|
||||
#define __GSEQUENCE_H__
|
||||
|
||||
|
||||
/* Warning
|
||||
*
|
||||
* Do not use this API. It is here, internal to gtk+, for 2.6 only.
|
||||
* In 2.8 the plan is to add a similar data structure to GLib.
|
||||
*/
|
||||
|
||||
typedef struct _GtkSequence GtkSequence;
|
||||
typedef struct _GtkSequenceNode *GtkSequencePtr;
|
||||
|
||||
/* GtkSequence */
|
||||
GtkSequence * _gtk_sequence_new (GDestroyNotify data_destroy);
|
||||
void _gtk_sequence_free (GtkSequence *seq);
|
||||
void _gtk_sequence_sort (GtkSequence *seq,
|
||||
GCompareDataFunc cmp_func,
|
||||
gpointer cmp_data);
|
||||
void _gtk_sequence_append (GtkSequence *seq,
|
||||
gpointer data);
|
||||
void _gtk_sequence_prepend (GtkSequence *seq,
|
||||
gpointer data);
|
||||
GtkSequencePtr _gtk_sequence_insert (GtkSequencePtr ptr,
|
||||
gpointer data);
|
||||
void _gtk_sequence_remove (GtkSequencePtr ptr);
|
||||
void _gtk_sequence_move (GtkSequencePtr ptr,
|
||||
GtkSequencePtr pos);
|
||||
void _gtk_sequence_swap (GtkSequencePtr a,
|
||||
GtkSequencePtr b);
|
||||
GtkSequencePtr _gtk_sequence_insert_sorted (GtkSequence *seq,
|
||||
gpointer data,
|
||||
GCompareDataFunc cmp_func,
|
||||
gpointer cmp_data);
|
||||
void _gtk_sequence_set (GtkSequencePtr ptr,
|
||||
gpointer data);
|
||||
void _gtk_sequence_insert_sequence (GtkSequencePtr ptr,
|
||||
GtkSequence *other_seq);
|
||||
void _gtk_sequence_concatenate (GtkSequence *seq1,
|
||||
GtkSequence *seq);
|
||||
void _gtk_sequence_remove_range (GtkSequencePtr begin,
|
||||
GtkSequencePtr end,
|
||||
GtkSequence **removed);
|
||||
gint _gtk_sequence_get_length (GtkSequence *seq);
|
||||
GtkSequencePtr _gtk_sequence_get_end_ptr (GtkSequence *seq);
|
||||
GtkSequencePtr _gtk_sequence_get_begin_ptr (GtkSequence *seq);
|
||||
GtkSequencePtr _gtk_sequence_get_ptr_at_pos (GtkSequence *seq,
|
||||
gint pos);
|
||||
void _gtk_sequence_sort_changed (GtkSequencePtr ptr,
|
||||
GCompareDataFunc cmp_func,
|
||||
gpointer cmp_data);
|
||||
void _gtk_sequence_foreach (GtkSequence *seq,
|
||||
GFunc func,
|
||||
gpointer data);
|
||||
|
||||
/* GtkSequencePtr */
|
||||
gboolean _gtk_sequence_ptr_is_end (GtkSequencePtr ptr);
|
||||
gboolean _gtk_sequence_ptr_is_begin (GtkSequencePtr ptr);
|
||||
gint _gtk_sequence_ptr_get_position (GtkSequencePtr ptr);
|
||||
GtkSequencePtr _gtk_sequence_ptr_next (GtkSequencePtr ptr);
|
||||
GtkSequencePtr _gtk_sequence_ptr_prev (GtkSequencePtr ptr);
|
||||
GtkSequencePtr _gtk_sequence_ptr_move (GtkSequencePtr ptr,
|
||||
guint leap);
|
||||
gpointer _gtk_sequence_ptr_get_data (GtkSequencePtr ptr);
|
||||
GtkSequence *_gtk_sequence_ptr_get_sequence (GtkSequencePtr ptr);
|
||||
|
||||
/* search */
|
||||
|
||||
/* return TRUE if you want to be called again with two
|
||||
* smaller segments
|
||||
*/
|
||||
typedef gboolean (* GtkSequenceSearchFunc) (GtkSequencePtr begin,
|
||||
GtkSequencePtr end,
|
||||
gpointer data);
|
||||
|
||||
void _gtk_sequence_search (GtkSequence *seq,
|
||||
GtkSequenceSearchFunc f,
|
||||
gpointer data);
|
||||
|
||||
/* debug */
|
||||
gint _gtk_sequence_calc_tree_height (GtkSequence *seq);
|
||||
|
||||
#endif /* __GSEQUENCE_H__ */
|
@ -51,6 +51,7 @@ noinst_PROGRAMS = \
|
||||
testtoolbar \
|
||||
stresstest-toolbar \
|
||||
testtreeedit \
|
||||
testtreemodel \
|
||||
testtreeview \
|
||||
testtreefocus \
|
||||
testtreeflow \
|
||||
@ -88,6 +89,7 @@ testspinbutton_DEPENDENCIES = $(TEST_DEPS)
|
||||
testtext_DEPENDENCIES = $(TEST_DEPS)
|
||||
testtextbuffer_DEPENDENCIES = $(TEST_DEPS)
|
||||
testtreeedit_DEPENDENCIES = $(DEPS)
|
||||
testtreemodel_DEPENDENCIES = $(DEPS)
|
||||
testtreeview_DEPENDENCIES = $(DEPS)
|
||||
testtreefocus_DEPENDENCIES = $(DEPS)
|
||||
testtreeflow_DEPENDENCIES = $(DEPS)
|
||||
@ -122,6 +124,7 @@ testtextbuffer_LDADD = $(LDADDS)
|
||||
testtoolbar_LDADD = $(LDADDS)
|
||||
stresstest_toolbar_LDADD = $(LDADDS)
|
||||
testtreeedit_LDADD = $(LDADDS)
|
||||
testtreemodel_LDADD = $(LDADDS)
|
||||
testtreeview_LDADD = $(LDADDS)
|
||||
testtreefocus_LDADD = $(LDADDS)
|
||||
testtreeflow_LDADD = $(LDADDS)
|
||||
@ -148,6 +151,9 @@ testgtk_SOURCES = \
|
||||
testtreeedit_SOURCES = \
|
||||
testtreeedit.c
|
||||
|
||||
testtreemodel_SOURCES = \
|
||||
testtreemodel.c
|
||||
|
||||
testtreeview_SOURCES = \
|
||||
prop-editor.c \
|
||||
testtreeview.c
|
||||
|
305
tests/testtreemodel.c
Normal file
305
tests/testtreemodel.c
Normal file
@ -0,0 +1,305 @@
|
||||
#include <malloc.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
static gint repeats = 2;
|
||||
static gint max_size = 8;
|
||||
|
||||
static GOptionEntry entries[] = {
|
||||
{ "repeats", 'r', 0, G_OPTION_ARG_INT, &repeats, "Average over N repetitions", "N" },
|
||||
{ "max-size", 'm', 0, G_OPTION_ARG_INT, &max_size, "Test up to 2^M items", "M" },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
||||
typedef void (ClearFunc)(GtkTreeModel *model);
|
||||
typedef void (InsertFunc)(GtkTreeModel *model,
|
||||
gint items,
|
||||
gint i);
|
||||
|
||||
static void
|
||||
list_store_append (GtkTreeModel *model,
|
||||
gint items,
|
||||
gint i)
|
||||
{
|
||||
GtkListStore *store = GTK_LIST_STORE (model);
|
||||
GtkTreeIter iter;
|
||||
gchar *text;
|
||||
|
||||
text = g_strdup_printf ("row %d", i);
|
||||
gtk_list_store_append (store, &iter);
|
||||
gtk_list_store_set (store, &iter, 0, i, 1, text, -1);
|
||||
g_free (text);
|
||||
}
|
||||
|
||||
static void
|
||||
list_store_prepend (GtkTreeModel *model,
|
||||
gint items,
|
||||
gint i)
|
||||
{
|
||||
GtkListStore *store = GTK_LIST_STORE (model);
|
||||
GtkTreeIter iter;
|
||||
gchar *text;
|
||||
|
||||
text = g_strdup_printf ("row %d", i);
|
||||
gtk_list_store_prepend (store, &iter);
|
||||
gtk_list_store_set (store, &iter, 0, i, 1, text, -1);
|
||||
g_free (text);
|
||||
}
|
||||
|
||||
static void
|
||||
list_store_insert (GtkTreeModel *model,
|
||||
gint items,
|
||||
gint i)
|
||||
{
|
||||
GtkListStore *store = GTK_LIST_STORE (model);
|
||||
GtkTreeIter iter;
|
||||
gchar *text;
|
||||
gint n;
|
||||
|
||||
text = g_strdup_printf ("row %d", i);
|
||||
n = g_random_int_range (0, i + 1);
|
||||
gtk_list_store_insert (store, &iter, n);
|
||||
gtk_list_store_set (store, &iter, 0, i, 1, text, -1);
|
||||
g_free (text);
|
||||
}
|
||||
|
||||
static gint
|
||||
compare (GtkTreeModel *model,
|
||||
GtkTreeIter *a,
|
||||
GtkTreeIter *b,
|
||||
gpointer data)
|
||||
{
|
||||
gchar *str_a, *str_b;
|
||||
gint result;
|
||||
|
||||
gtk_tree_model_get (model, a, 1, &str_a, -1);
|
||||
gtk_tree_model_get (model, b, 1, &str_b, -1);
|
||||
|
||||
result = strcmp (str_a, str_b);
|
||||
|
||||
g_free (str_a);
|
||||
g_free (str_b);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
tree_store_append (GtkTreeModel *model,
|
||||
gint items,
|
||||
gint i)
|
||||
{
|
||||
GtkTreeStore *store = GTK_TREE_STORE (model);
|
||||
GtkTreeIter iter;
|
||||
gchar *text;
|
||||
|
||||
text = g_strdup_printf ("row %d", i);
|
||||
gtk_tree_store_append (store, &iter, NULL);
|
||||
gtk_tree_store_set (store, &iter, 0, i, 1, text, -1);
|
||||
g_free (text);
|
||||
}
|
||||
|
||||
static void
|
||||
tree_store_prepend (GtkTreeModel *model,
|
||||
gint items,
|
||||
gint i)
|
||||
{
|
||||
GtkTreeStore *store = GTK_TREE_STORE (model);
|
||||
GtkTreeIter iter;
|
||||
gchar *text;
|
||||
|
||||
text = g_strdup_printf ("row %d", i);
|
||||
gtk_tree_store_prepend (store, &iter, NULL);
|
||||
gtk_tree_store_set (store, &iter, 0, i, 1, text, -1);
|
||||
g_free (text);
|
||||
}
|
||||
|
||||
static void
|
||||
tree_store_insert_flat (GtkTreeModel *model,
|
||||
gint items,
|
||||
gint i)
|
||||
{
|
||||
GtkTreeStore *store = GTK_TREE_STORE (model);
|
||||
GtkTreeIter iter;
|
||||
gchar *text;
|
||||
gint n;
|
||||
|
||||
text = g_strdup_printf ("row %d", i);
|
||||
n = g_random_int_range (0, i + 1);
|
||||
gtk_tree_store_insert (store, &iter, NULL, n);
|
||||
gtk_tree_store_set (store, &iter, 0, i, 1, text, -1);
|
||||
g_free (text);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
gint i;
|
||||
gint n;
|
||||
gboolean found;
|
||||
GtkTreeIter iter;
|
||||
} FindData;
|
||||
|
||||
static gboolean
|
||||
find_nth (GtkTreeModel *model,
|
||||
GtkTreePath *path,
|
||||
GtkTreeIter *iter,
|
||||
gpointer data)
|
||||
{
|
||||
FindData *fdata = (FindData *)data;
|
||||
|
||||
if (fdata->i >= fdata->n)
|
||||
{
|
||||
fdata->iter = *iter;
|
||||
fdata->found = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
fdata->i++;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
tree_store_insert_deep (GtkTreeModel *model,
|
||||
gint items,
|
||||
gint i)
|
||||
{
|
||||
GtkTreeStore *store = GTK_TREE_STORE (model);
|
||||
GtkTreeIter iter;
|
||||
gchar *text;
|
||||
FindData data;
|
||||
gint n;
|
||||
|
||||
text = g_strdup_printf ("row %d", i);
|
||||
data.n = g_random_int_range (0, items);
|
||||
data.i = 0;
|
||||
data.found = FALSE;
|
||||
if (data.n < i)
|
||||
gtk_tree_model_foreach (model, find_nth, &data);
|
||||
gtk_tree_store_insert (store, &iter, data.found ? &(data.iter) : NULL, n);
|
||||
gtk_tree_store_set (store, &iter, 0, i, 1, text, -1);
|
||||
g_free (text);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
test_run (gchar *title,
|
||||
GtkTreeModel *store,
|
||||
ClearFunc *clear,
|
||||
InsertFunc *insert)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
gint i, k, d, items;
|
||||
gchar *text;
|
||||
GTimer *timer;
|
||||
gdouble elapsed;
|
||||
int uordblks_before;
|
||||
|
||||
g_print ("%s (average over %d runs, time in milliseconds)\n"
|
||||
"items \ttime \ttime/item \tused memory\n", title, repeats);
|
||||
|
||||
timer = g_timer_new ();
|
||||
|
||||
for (k = 0; k < max_size; k++)
|
||||
{
|
||||
items = 1 << k;
|
||||
elapsed = 0.0;
|
||||
for (d = 0; d < repeats; d++)
|
||||
{
|
||||
(*clear)(store);
|
||||
uordblks_before = mallinfo().uordblks;
|
||||
g_timer_reset (timer);
|
||||
g_timer_start (timer);
|
||||
for (i = 0; i < items; i++)
|
||||
(*insert) (store, items, i);
|
||||
g_timer_stop (timer);
|
||||
elapsed += g_timer_elapsed (timer, NULL);
|
||||
}
|
||||
|
||||
elapsed = elapsed * 1000 / repeats;
|
||||
g_print ("%d \t%lf \t%lf \t%ldk\n",
|
||||
items, elapsed, elapsed/items, (mallinfo().uordblks - uordblks_before) / 1024);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GtkTreeModel *model;
|
||||
GOptionContext *context;
|
||||
|
||||
gtk_init (&argc, &argv);
|
||||
|
||||
context = g_option_context_new ("");
|
||||
g_option_context_add_main_entries (context, entries, "");
|
||||
g_option_context_parse (context, &argc, &argv, NULL);
|
||||
g_option_context_free (context);
|
||||
|
||||
model = GTK_TREE_MODEL (gtk_list_store_new (2, G_TYPE_INT, G_TYPE_STRING));
|
||||
|
||||
test_run ("list store append",
|
||||
model,
|
||||
(ClearFunc*)gtk_list_store_clear,
|
||||
(InsertFunc*)list_store_append);
|
||||
|
||||
test_run ("list store prepend",
|
||||
model,
|
||||
(ClearFunc*)gtk_list_store_clear,
|
||||
(InsertFunc*)list_store_prepend);
|
||||
|
||||
test_run ("list store insert",
|
||||
model,
|
||||
(ClearFunc*)gtk_list_store_clear,
|
||||
(InsertFunc*)list_store_insert);
|
||||
|
||||
gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (model),
|
||||
compare, NULL, NULL);
|
||||
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
|
||||
GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
|
||||
GTK_SORT_ASCENDING);
|
||||
|
||||
test_run ("list store insert (sorted)",
|
||||
model,
|
||||
(ClearFunc*)gtk_list_store_clear,
|
||||
(InsertFunc*)list_store_insert);
|
||||
|
||||
g_object_unref (model);
|
||||
|
||||
model = GTK_TREE_MODEL (gtk_tree_store_new (2, G_TYPE_INT, G_TYPE_STRING));
|
||||
|
||||
test_run ("tree store append",
|
||||
model,
|
||||
(ClearFunc*)gtk_tree_store_clear,
|
||||
(InsertFunc*)tree_store_append);
|
||||
|
||||
test_run ("tree store prepend",
|
||||
model,
|
||||
(ClearFunc*)gtk_tree_store_clear,
|
||||
(InsertFunc*)tree_store_prepend);
|
||||
|
||||
test_run ("tree store insert (flat)",
|
||||
model,
|
||||
(ClearFunc*)gtk_tree_store_clear,
|
||||
(InsertFunc*)tree_store_insert_flat);
|
||||
|
||||
test_run ("tree store insert (deep)",
|
||||
model,
|
||||
(ClearFunc*)gtk_tree_store_clear,
|
||||
(InsertFunc*)tree_store_insert_deep);
|
||||
|
||||
gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (model),
|
||||
compare, NULL, NULL);
|
||||
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
|
||||
GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
|
||||
GTK_SORT_ASCENDING);
|
||||
|
||||
test_run ("tree store insert (flat, sorted)",
|
||||
model,
|
||||
(ClearFunc*)gtk_tree_store_clear,
|
||||
(InsertFunc*)tree_store_insert_flat);
|
||||
|
||||
test_run ("tree store insert (deep, sorted)",
|
||||
model,
|
||||
(ClearFunc*)gtk_tree_store_clear,
|
||||
(InsertFunc*)tree_store_insert_deep);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user